﻿/*
 * Rappelz: Endless Odyssey - The first free open source Rappelz server emulator
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using GameServer;
using Rappelz.GameServer.Network.GameClient;
using Rappelz.GameServer.Database;
using Rappelz.GameServer.Network;

namespace Rappelz.GameServer.Scripting
{
    public class LuaVMException : Exception
    {
        public LuaVMException(string msg)
            : base(msg)
        {
        }
    }


    public class LuaVM
    {
        private static IntPtr m_lua_State = IntPtr.Zero;
        private static List<Delegate> m_refs = new List<Delegate>();
        private static List<string> m_errors = new List<string>();

        private static LuaVM m_instance = null;

        private object lockObj = new object();

        private GameObject m_obj = null;

        public static LuaVM Instance
        {
            get { return LuaVM.m_instance; }
        }

        public static List<string> Errors
        {
            get { return m_errors; }
            set { m_errors = value; }
        }

        /// <summary>
        /// Is the top of the lua stack nil ?
        /// </summary>
        private bool IsTopNil
        {
            get
            {
                return Lua.lua_type(m_lua_State, -1) == Lua.LUA_TNIL ? true : false;
            }
        }

        /// <summary>
        /// Default constructor, initializes a new Lua state by calling ResetLua() method
        /// </summary>
        public LuaVM()
        {
            //initialize lua
            ResetLua();
        }

        /// <summary>
        /// Constructor, initializes a new Lua state by calling ResetLua() method
        /// Asssigns the internal errorlog to the passed in value
        /// </summary>
        public LuaVM(List<string> errorLog)
            : this()
        {
            if (errorLog != null)
                m_errors = errorLog;

            //initialize lua
            ResetLua();
        }

        /// <summary>
        /// Constructor, initializes a new Lua state by calling ResetLua() method
        /// if lua is already open, then close current lua state, and assign the passed in state as the curent state
        /// </summary>
        public LuaVM(IntPtr lua_State)
        {
            //if lua is already open, then close current lua state
            CloseLua();
            //assign injected lua state
            m_lua_State = lua_State;
        }

        /// <summary>
        /// Closes lua and clear errorlog and any references to functions that was registered with lua
        /// </summary>
        public static void CloseLua()
        {
            if (m_lua_State != IntPtr.Zero)
            {
                Lua.lua_close(m_lua_State);
            }
            //clear any references to callbacks to allow the garbage collector collect them
            m_refs.Clear();
            m_errors.Clear();
        }

        /// <summary>
        /// Closes lua by calling CloseLua() method, then opens a new lua state with all libs open
        /// </summary>
        public static void ResetLua()
        {
            //if lua is already open, then close current lua state, and open a new one
            if(m_instance != null)
            {
                lock(m_instance.lockObj)
                {
                    CloseLua();

                    //open lua
                    m_lua_State = Lua.lua_open();

                    //open libraries
                    Lua.luaL_openlibs(m_lua_State);
                }
            }
            else
            {
                CloseLua();

                //open lua
                m_lua_State = Lua.lua_open();

                //open libraries
                Lua.luaL_openlibs(m_lua_State);
            }
        }

        /// <summary>
        /// looks in the lua stack top if theres a string on top
        /// if it is a string then it adds it as an error message to the Errors list
        /// Clears the method off the stack by setting the top to 0
        /// </summary>
        public void LogError()
        {
            //log error
            if (Lua.lua_isstring(m_lua_State, -1) > 0)
            {
                string s = Lua.lua_tostring(m_lua_State, -1);
                Errors.Add(s);
                Error(s);
            }

            //clear the stack
            Lua.lua_settop(m_lua_State, 0);
        }

        public static void Error(String l, params object[] args)
        {
            if (Config.bDebug)  //print full information about where the error come from if in debug mode, else just print Lua error (retrieving stacktrace may be slow)
                Globals.Log.Error("Lua error: " + String.Format(l, args) + ", stacktrace: " + Environment.NewLine + Environment.StackTrace);
            else Globals.Log.Error(l,args);

            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                Messages.SendChatMessage(false, 50, "@SCRIPT", player, String.Format(l,args), 0);
            }
        }


        public static int cprint(IntPtr state)
        {
            int i;
            string sz;

            int n = Lua.lua_gettop(state);
            for(i = 1; i <= n; ++i)
            {
                sz = "";
                if (Lua.lua_isnumber(state, i) != 0)
                {
                    double num = Lua.lua_tonumber(state, i);
                    sz = num.ToString();
                }
                else if (Lua.lua_isstring(state, i) != 0)
                {
                    sz = Lua.lua_tostring(state, i);
                }
                Error(sz);
            }
            return 0;
        }


        /// <summary>
        /// Does the same as the staic method CloseLua(), but this method is a wrapper as an instance method
        /// </summary>
        public void StopEngineAndCleanup()
        {
            CloseLua();
        }

        /// <summary>
        /// Registers a .net method denoted by the delegate Lua.LuaFunction as a lua function
        /// the function will take on the name luaFuncName, in lua
        /// </summary>
        /// <param name="func">.net function to register with lua</param>
        /// <param name="luaFuncName">name of .net function in lua</param>
        public void RegisterFunction(Lua.LuaFunction func, string luaFuncName)
        {
            Lua.lua_register(m_lua_State, luaFuncName, func);

            //make sure the delegate callback is not collected by the garbage collector before
            //unmanaged code has called back
            m_refs.Add(func);
        }

        /// <summary>
        /// Creates a table with tableName if it does not already exist.
        /// After creation or if the table already exists, stack will be empty and balanced.
        /// </summary>
        /// <param name="tableName"></param>
        public void CreateLuaTable(string tableName)
        {
            Lua.lua_getglobal(m_lua_State, tableName);
            if (IsTopNil)
            {
                //remove the nil value
                Lua.lua_pop(m_lua_State, 1);
                Lua.lua_newtable(m_lua_State);
                Lua.lua_setglobal(m_lua_State, tableName);
                //stack is empty
            }
            else
            {
                //remove the existing table from the stack
                Lua.lua_pop(m_lua_State, 1);
            }
        }

        /// <summary>
        /// Gets the value of a field of a table and returns it as type object i.e. return luaTable.someField
        /// After the call the lua stack is balanced
        /// </summary>
        /// <param name="tableName">name of lua table</param>
        /// <param name="fieldName">name of table field</param>
        /// <returns>returns luaTable.someField</returns>
        public object GetTableField(string tableName, string fieldName)
        {
            //push table on the stack
            Lua.lua_getglobal(m_lua_State, tableName);

            if (IsTopNil)
                throw new LuaVMException("GetTableField, the table does not exist: " + tableName);

            //push table field name on the stack
            Lua.lua_pushstring(m_lua_State, fieldName);

            //get value of field of table: get tableName[fieldName]
            Lua.lua_gettable(m_lua_State, -2);

            //get the result of the stack
            int luaType = 0;
            object value = GetValueOfStack(out luaType);

            //pop table of the stack
            Lua.lua_pop(m_lua_State, 1);

            //stack is balanced
            return value;
        }

        /// <summary>
        /// Gets the value of a field of a lua table and returns it as type object i.e. return luaTable.someField
        /// The table to operate on must currently be on top of the lua stack.
        /// After the call the lua table is still on top of the stack
        /// </summary>
        /// <param name="fieldName">
        /// the name of the field, belonging to a lua table currently sitting on 
        /// top of the lua stack
        /// </param>
        /// <returns>returns luaTable.someField</returns>
        public object GetTableField(string fieldName)
        {
            if (IsTopNil)
                throw new LuaVMException("GetTableField, no table on top of stack");

            //push table field name on the stack
            Lua.lua_pushstring(m_lua_State, fieldName);

            //get value of field of table: get tableName[fieldName]
            Lua.lua_gettable(m_lua_State, -2);

            //get the result of the stack
            int luaType = 0;
            object value = GetValueOfStack(out luaType);

            //table is still on top of the stack
            return value;
        }

        /// <summary>
        /// Sets a field of a lua table to a lua variable identified by luaIdentifier i.e. luaTable.someField = luaVariable
        /// After the call the lua stack is balanced.
        /// </summary>
        /// <param name="tableName">name of the lua table</param>
        /// <param name="fieldName">name of the field</param>
        /// <param name="luaIdentifier">the identifier identifying the lua variable</param>
        public void SetTableFieldToLuaIdentifier(string tableName, string fieldName, string luaIdentifier)
        {
            Lua.lua_getglobal(m_lua_State, tableName);
            Lua.lua_pushstring(m_lua_State, fieldName);
            Lua.lua_getglobal(m_lua_State, luaIdentifier);
            Lua.lua_settable(m_lua_State, -3);
            Lua.lua_pop(m_lua_State, 1);
            //stack is balanced
        }

        /// <summary>
        /// Sets a field of a lua table to a lua variable identified by luaIdentifier i.e. luaTable.someField = luaVariable
        /// The table to operate on must currently be on top of the lua stack.
        /// After the call the lua table is still on top of the stack.
        /// </summary>
        /// <param name="fieldName">name of the field</param>
        /// <param name="luaIdentifier">the identifier identifying the lua variable</param>
        public void SetTableFieldToLuaIdentifier(string fieldName, string luaIdentifier)
        {
            Lua.lua_pushstring(m_lua_State, fieldName);
            Lua.lua_getglobal(m_lua_State, luaIdentifier);
            Lua.lua_settable(m_lua_State, -3);
            //table is still on top of the stack
        }

        /// <summary>
        /// Sets a field of a lua table to a .net variable value i.e. luaTable.someField = value of .net variable.
        /// After the call the lua stack is balanced.
        /// </summary>
        /// <param name="tableName">name of the lua table</param>
        /// <param name="fieldName">name of the field</param>
        /// <param name="value">.net variable</param>
        public void SetTableField(string tableName, string fieldName, object value)
        {
            //push table on the stack
            Lua.lua_getglobal(m_lua_State, tableName);

            if (IsTopNil)
                throw new LuaVMException("SetTableField, the table does not exist: " + tableName);

            //push table field name on the stack
            Lua.lua_pushstring(m_lua_State, fieldName);

            //push value on the stack
            PushBasicValue(value);

            //set field of table to value: tableName[fieldName]=value
            Lua.lua_settable(m_lua_State, -3);
            //pop table of the stack
            Lua.lua_pop(m_lua_State, 1);
            //stack is balanced
        }

        /// <summary>
        /// Sets a field of a lua table to a .net variable value i.e. luaTable.someField = value of .net variable.
        /// After the call the lua table is still on top of the stack.
        /// </summary>
        /// <param name="fieldName">name of the field</param>
        /// <param name="value">.net variable</param>
        public void SetTableField(string fieldName, object value)
        {
            if (IsTopNil)
                throw new LuaVMException("SetTableField, no table on top of the stack");

            //push table field name on the stack
            Lua.lua_pushstring(m_lua_State, fieldName);

            //push value on the stack
            PushBasicValue(value);

            //set field of table to value: tableName[fieldName]=value
            Lua.lua_settable(m_lua_State, -3);

            //table is still on top of the stack
        }

        /// <summary>
        /// Pops the value sitting on top of the lua stack
        /// </summary>
        /// <param name="luaType">the lua type of the value that was retrieved from the stack, is stored in this out parameter</param>
        /// <returns>the value popped off the stack</returns>
        public object GetValueOfStack(out int luaType)
        {
            luaType = 0;
            object value = null;
            switch (Lua.lua_type(m_lua_State, -1))
            {
                case Lua.LUA_TNONE:
                    {
                        value = null;
                        luaType = Lua.LUA_TNONE;
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }
                case Lua.LUA_TNIL:
                    {
                        value = null;
                        luaType = Lua.LUA_TNIL;
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }
                case Lua.LUA_TSTRING:
                    {
                        luaType = Lua.LUA_TSTRING;
                        value = Lua.lua_tostring(m_lua_State, -1);
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }
                case Lua.LUA_TNUMBER:
                    {
                        luaType = Lua.LUA_TNUMBER;
                        value = Lua.lua_tonumber(m_lua_State, -1);
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }
                case Lua.LUA_TBOOLEAN:
                    {
                        luaType = Lua.LUA_TBOOLEAN;
                        int intToBool = Lua.lua_toboolean(m_lua_State, -1);
                        value = intToBool > 0 ? true : false;
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }
                case Lua.LUA_TTABLE:
                    {
                        luaType = Lua.LUA_TTABLE;
                        value = "table";
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }
                default:
                    {
                        value = null;
                        //pop value from stack
                        Lua.lua_pop(m_lua_State, 1);
                        break;
                    }

                //case Lua.LUA_TINTEGER:
                //{
                //    value = Lua.lua_tointeger(m_lua_State, -1);
                //    //pop value from stack
                //    Lua.lua_pop(m_lua_State, 1);
                //    break;
                //}
            }

            return value;
        }

        /// <summary>
        /// Pushes the value on to the lua stack based on value.GetType(), and how that type maps to a lua type.
        /// Pushes nil if object is null or typeof object is not a basic type
        /// </summary>
        /// <param name="value">the value to push on to the stack</param>
        public void PushBasicValue(object value)
        {
            if (value == null)
            {
                Lua.lua_pushnil(m_lua_State);
                return;
            }
            if (value.GetType() == typeof(string))
            {
                Lua.lua_pushstring(m_lua_State, value.ToString());
                return;
            }
            if (value.GetType() == typeof(bool))
            {
                Lua.lua_pushboolean(m_lua_State, (bool)value);
                return;
            }
            if (value.GetType() == typeof(decimal))
            {
                Lua.lua_pushnumber(m_lua_State, Convert.ToDouble(((decimal)value)));
                return;
            }
            if (value.GetType() == typeof(float))
            {
                Lua.lua_pushnumber(m_lua_State, Convert.ToDouble(((float)value)));
                return;
            }
            if (value.GetType() == typeof(double))
            {
                Lua.lua_pushnumber(m_lua_State, Convert.ToDouble(((double)value)));
                return;
            }
            if (value.GetType() == typeof(int))
            {
                Lua.lua_pushinteger(m_lua_State, (int)value);
                return;
            }
            if (value.GetType() == typeof(DateTime))
            {
                Lua.lua_pushstring(m_lua_State, ((DateTime)value).ToString());
                return;
            }
            if (value.GetType() == typeof(Guid))
            {
                Lua.lua_pushstring(m_lua_State, ((Guid)value).ToString());
                return;
            }
            if (value.GetType().IsEnum)
            {
                Lua.lua_pushstring(m_lua_State, value.ToString());
                return;
            }

            Lua.lua_pushnil(m_lua_State);

        }


        public static bool Init()
        {
            if (m_instance == null)
                m_instance = new LuaVM();

            lock (m_instance.lockObj)
            {
                foreach (string st in Directory.GetFiles("Resource\\scripts\\", "*.lua", SearchOption.AllDirectories))
                {
                    try
                    {
                        int res = Lua.luaL_dofile(m_lua_State, st);
                        if (res != 0)
                            m_instance.LogError();
                    }
                    catch (Exception err)
                    {
                        Globals.Log.Error("Error loading a lua script ({0}) : {1}", st, err);
                    }
                }


                m_instance.RegisterFunction(new Lua.LuaFunction(cprint), "cprint");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddState), "add_state");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetValue), "get_value");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetValue), "gv");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetValue), "set_value");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetValue), "sv");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetLocalInfo), "get_local_info");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetProperChannelNo), "get_proper_channel_num");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetLayerOfChannel), "get_layer_of_channel");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_Conv), "sconv");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_Message), "message");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetEnv), "set_env");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetEnv), "get_env");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_OpenPopup), "open_popup");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetPlayerFlag), "get_flag");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetPlayerFlag), "set_flag");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_RemovePlayerFlag), "del_flag");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetServerCategory), "get_server_category");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetCurrentLocationId), "call_lc_In");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddRespawnInfo), "respawn");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddDungeonGuardianRespawnInfo), "respawn_guardian");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddDungeonEnvironmentalGuardianRespawnInfo), "respawn_environmental_guardian");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddRareMobRespawnInfo), "respawn_rare_mob");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddRoamingMobRespawnInfo), "respawn_roaming_mob");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddRaidRespawnInfo), "raid_respawn");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddRaidRespawnInfo), "raid_respawn_rare_mob");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_DialogTitle), "dlg_title");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_DialogText), "dlg_text");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_DialogMenu), "dlg_menu");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_DialogShow), "dlg_show");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetQuestProgress), "get_quest_progress");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_DialogTextWithoutQuest), "dlg_text_without_quest_menu");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_QuestInfo), "quest_info");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_StartQuest), "start_quest");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_WarpToRevivePosition), "warp_to_revive_position");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_EndQuest), "end_quest");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ShowStorage), "open_storage");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_Warp), "warp");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SendGoldChaosUpdate), "update_gold_chaos");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SavePlayer), "save");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetNPCId), "get_npc_id");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_FindItem), "find_item");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetStateLevel), "get_state_level");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ShowMarket), "open_market");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_WarpToDungeon), "enter_dungeon");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetOwnDungeonID), "get_own_dungeon_id");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetSiegeDungeonID), "get_siege_dungeon_id");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetWearItemHandle), "get_wear_item_handle");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemHandle), "get_item_handle");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemName), "get_item_name");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemCode), "get_item_code");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetItemLevel), "set_item_level");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemLevel), "get_item_level");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetItemEnhance), "set_item_enhance");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemEnhance), "get_item_enhance");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemRank), "get_item_rank");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemPrice), "get_item_price");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemEndurance), "get_item_endurance");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetItemEndurance), "set_item_endurance");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemSocketCode), "get_socket_info");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetItemSocketCode), "set_socket_info");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ItemName), "get_item_name_by_code");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetItemNameId), "get_item_name_id");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetCreatureHandle), "get_creature_handle");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetCreatureValue), "get_creature_value");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetCreatureValue), "set_creature_value");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_CreatureEvolution), "creature_evolution");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_Notice), "notice");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_Announce), "announce");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_LocalNotice), "local_notice");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_Chat), "chat");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GChat), "gchat");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_InsertItem), "insert_item");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddMonster), "add_npc");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SetWayPointType), "set_way_point_type");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddWayPoint), "add_way_point");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_DeleteItem), "delete_item");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SpawnFieldProp), "spawn_fieldprop");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddHotspotSquare), "add_hotspot_square");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_AddHotspot), "add_hotspot");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_RemoveAllHotspots), "remove_hotspots");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ShowSoulStoneCraftWindow), "show_soulstone_craft_window");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ShowSoulStoneRepairWindow), "show_soulstone_repair_window");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ShowQuestDialog), "show_quest_dialog");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_ShowCreateGuild), "show_guild_create");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_CheckValidGuildName), "check_valid_guild_name");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_CreateGuild), "create_guild");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_SpawnedCount), "spawned_count");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_UpdateQuest), "update_quest");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_StartQuestTimer), "activate_quest_timer");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetMonsterID), "get_monster_id");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_RespawnNearMonster), "respawn_near_monster");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_MonsterSkillCast), "monster_skill_cast");
                m_instance.RegisterFunction(new Lua.LuaFunction(SCRIPT_GetDungeonRelation), "get_dungeon_relation");

                // 	LuaVM::Inst()->RegisterFunction("", );
            }

            // 	LuaVM::Inst()->RegisterFunction("", );
            // 	LuaVM::Inst()->RegisterFunction("", );

            // 	LuaVM::Inst()->RegisterFunction("", );
            // 	LuaVM::Inst()->RegisterFunction("", );
            // 	LuaVM::Inst()->RegisterFunction("", );

            // 	        LuaVM.RegisterFunction("", );


            //    LuaVM::RegisterFunction(v181, "", SCRIPT_SetWayPointType);

            // 	LuaVM::Inst()->RegisterFunction("", );


            // 	        LuaVM.RegisterFunction("", );

            // 	LuaVM::Inst()->RegisterFunction("", );

            // 	LuaVM::Inst()->RegisterFunction("", SCRIPT_WarpToRevivePosition);
            // 	LuaVM::Inst()->RegisterFunction("quest_text_without_quest_menu", SCRIPT_QuestTextWithoutQuest);
            // 	LuaVM::Inst()->RegisterFunction("force_start_quest", SCRIPT_ForceStartQuest);
            // 	LuaVM::Inst()->RegisterFunction("get_last_accept_quest", SCRIPT_GetLastAcceptQuest);

            return true;
        }

        public static bool DeInit()
        {
            return false;
        }
//         public static void BindLogOutputFunction(function  *)
//         public static void Log(const char *)
//         public static void LogPrintf(const char *, <NoType>)
//         public static struct lua_State * lockState()
//         public static void pushFunction(const char *)
//         public static bool call(bool, class std::basic_string<char,std::char_traits<char>,std::allocator<char> > *)
//         public static void pushNumber(double)
//         public static void pushString(const char *)
//         public static void unlockState()
//         public static void ResetLoadedScriptList()
//         public static bool LoadScript(const char *, const bool)
//         public static bool RunFile(const char *, const bool)

        public bool RunString(GameObject obj, string szString, out string szRetString)
        {
            lock(lockObj)
            {
                m_obj = obj;
                szRetString = "";
                if (szString == "0")
                    return true;
                if (m_lua_State == IntPtr.Zero)
                    return false;

                if (Lua.luaL_dostring(m_lua_State, szString) == 0)
                    return true;

                //log the error if possible
                LogError();
            }
            return false;
        }

        public bool RunString(GameObject obj, string szString)
        {
            string res;
            return RunString(obj, szString, out res);
        }

        public bool RunString(string szString)
        {
            string res;
            return RunString(null, szString, out res);
        }

//         public static bool RunFunction(const char *, <NoType>)
//         public static bool RegisterFunction(const char *, function  *)
//         public static LuaVM * GlobalInst()
//         public static LuaVM * LuaVM::Inst()
// 
//        private static System.Program program = new Program()
//         static, [00000000][0000:00000000], Static Member, Type: const char, LUA_FILE_FORMAT_TAG_0
//         static, [00000000][0000:00000000], Static Member, Type: const char, LUA_FILE_FORMAT_TAG_1
//         static, [00000000][0000:00000000], Static Member, Type: const unsigned int, LUA_FILE_VERSION
// 
//             UserDefinedType:   LUA_INFO
// Function       :     public void LUA_INFO(const struct LuaVM::LUA_INFO &)
// Function       :     public void LuaVM::LUA_INFO::LUA_INFO()
// Data           :     this+0x0, Member, Type: int, prev_stack_top
// Data           :     this+0x4, Member, Type: int, arg_cnt
// Data           :     this+0x8, Member, Type: struct lua_State *, pState
// Data           :     this+0xC, Member, Type: class XCriticalSection, cs
// 
// Function       :     public void ~LUA_INFO()
// Function       :     public struct LuaVM::LUA_INFO & operator=(const struct LuaVM::LUA_INFO &)
// Function       :     public void * __vecDelDtor(unsigned int)
// 
//         public static bool Reload()
//         public static bool LuaVM::InitThread(volatile struct LuaVM::LUA_INFO * *)
//         public static bool DeInitThread()
//         Function       :   private void LuaVM::LuaVM(bool)
// Function       :   private void ~LuaVM()
// 
// Data           :   this+0x0, Member, Type: struct _LOG_FUNC *, m_pLogFunc
// Function       :   private struct LuaVM::LUA_INFO * LuaVM::getLuaInfo()
// Function       :   private void LuaVM::reload(struct lua_State *)
// Function       :   private const bool LuaVM::doFile(struct lua_State *, const char *, const bool)
// Data           :   static, [002505A0][0003:000345A0], Static Member, Type: class std::vector<LuaVM::LUA_INFO *,std::allocator<LuaVM::LUA_INFO *> >, m_vStateList
// UserDefinedType:     std::vector<LuaVM::LUA_INFO *,std::allocator<LuaVM::LUA_INFO *> >
// 
// Data           :   static, [00250544][0003:00034544], Static Member, Type: class std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,int (__cdecl*)(lua_State *),std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,int (__cdecl*)(lua_State *)> > >, m_mapFuncList
// UserDefinedType:     std::map<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,int (__cdecl*)(lua_State *),std::less<std::basic_string<char,std::char_traits<char>,std::allocator<char> > >,std::allocator<std::pair<std::basic_string<char,std::char_traits<char>,std::allocator<char> > const ,int (__cdecl*)(lua_State *)> > >
// 
// UserDefinedType:   LuaScriptInfo
// Function       :     public void LuaVM::LuaScriptInfo::LuaScriptInfo(const struct LuaVM::LuaScriptInfo &)
// Function       :     public void LuaScriptInfo(const char *, const bool)
// Function       :     public const bool operator==(const struct LuaVM::LuaScriptInfo &)
// Data           :     this+0x0, Member, Type: class std::basic_string<char,std::char_traits<char>,std::allocator<char> >, m_strFilename
// 
// Data           :     this+0x1C, Member, Type: bool, m_bEncrypted
// Function       :     public void LuaVM::LuaScriptInfo::~LuaScriptInfo()
// Function       :     public struct LuaVM::LuaScriptInfo & LuaVM::LuaScriptInfo::operator=(const struct LuaVM::LuaScriptInfo &)
// Function       :     public void * __vecDelDtor(unsigned int)
// 
// Data           :   static, [00250590][0003:00034590], Static Member, Type: class std::vector<LuaVM::LuaScriptInfo,std::allocator<LuaVM::LuaScriptInfo> >, m_vScriptList
// UserDefinedType:     std::vector<LuaVM::LuaScriptInfo,std::allocator<LuaVM::LuaScriptInfo> >
// 
// Data           :   this+0x4, Member, Type: bool, m_bIsGlobalInstance
// Data           :   this+0x5, Member, Type: bool, m_bInit

        public static int SCRIPT_SetWayPointType(IntPtr state)
        {
            if ( Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                GameContent.SetWayPointType((int)Lua.lua_tonumber(state, 1), (int)Lua.lua_tonumber(state, 2));
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_SetWayPointType() : invalid argument");
            }
            return 0;
        }

        public static int SCRIPT_AddWayPoint(IntPtr state)
        {
            if ( Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0 && Lua.lua_isnumber(state, 3) != 0)
            {
                GameContent.AddWayPoint((int)Lua.lua_tonumber(state, 1), (float)Lua.lua_tonumber(state, 2),(float)Lua.lua_tonumber(state, 3));
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddWayPoint() : invalid argument");
            }
            return 0;
        }

        public static int SCRIPT_AddState(IntPtr state)
        {

            int count = Lua.lua_gettop(state);

            if (count >= 3)
            {
                int nStateID = (int)Lua.lua_tonumber(state, 1);
                int nLevel = (int)Lua.lua_tonumber(state, 2);
                uint time = (uint)Lua.lua_tonumber(state, 3);
                if(Instance.m_obj != null)
                {
                    try
                    {
                        Creature c = (Creature) Instance.m_obj;
                        if (c != null)
                        {
                            uint start_time = Globals.GetArTime();
                            uint end_time = start_time + time;
                            bool bAura = false;
                            if (time == 0xffffffff)
                            {
                                end_time = 0xffffffff;
                                bAura = true;
                            }
                            //v7 = v3->baseclass_0.baseclass_0.baseclass_0.vfptr->GetHandle((ArSchedulerObject *)v3);
                            c.AddState(State.StateType.Normal, (State.StateCode) nStateID, c.m_hHandle, nLevel, start_time, end_time, bAura, 0,"");
                        }
                    }
                    catch (System.Exception ex)
                    {
                        Error("SCRIPT_AddState error: {0}", ex);	
                    }

                }
            }
            return 1;
        }

        public static int SCRIPT_GetValue(IntPtr state)
        {
            if (Lua.lua_gettop(state) < 1)
                return 0;

            Creature c = Instance.m_obj as Creature;
            Player p = Instance.m_obj as Player;
            if (c == null)
            {
                Lua.lua_pushnumber(state, 0.0);
                return 1;
            }

            string str = Lua.lua_tostring(state, 1);

            double ret = 0.0;
            switch(str)
            {
                case "race":
                    ret = (double) c.m_nRace;
                    break;

                case "job":
                    ret = (double) c.m_nJob;
                    break;

                case "max_hp":
                    ret = (double) c.m_nMaxHP;
                    break;

                case "max_mp":
                    ret = (double) c.m_nMaxMP;
                    break;

                case "x":
                    ret = (double) c.mv.x;
                    break;

                case "y":
                    ret = (double) c.mv.y;
                    break;

                case "level":
                case "lv":
                    ret = (double)c.m_nLevel;
                    break;

                //case "auto_used":  //typo ?
                case "auto_user":
                    ret = (double) 0.0;//c.m_nMaxMP;
                    break;

                case "job_depth":
                    ret = (double)c.GetJobDepth();
                    break;

                case "job_level":
                    ret = (double)c.GetJobLevel();
                    break;

                case "stamina":
                    ret = (double)p.m_nStamina;
                    break;

                case "gold":
                    ret = (double)p.m_nGold;
                    break;

                case "guild_id":
                    ret = (double)p.m_nGuildId;
                    break;

                case "layer":
                    ret = (double)p.m_layer;
                    break;

                case "permission":
                    ret = (double)p.m_nPermission;
                    break;

                case "chaos":
                    ret = (double)p.m_nChaos;
                    break;

                case "jp":
                    ret = (double)p.m_nJobPoint;
                    break;

                case "tp":
                    ret = (double)p.m_nTP;
                    break;

                case "name":
                    Lua.lua_pushstring(state, p.GetName());
                    return 1;

                default:
                    Error("SCRIPT_GetValue unknown field: {0}", str);
                    break;
            }

            Lua.lua_pushnumber(state, ret);
            return 1;
        }

        public static int SCRIPT_GetLocalInfo(IntPtr lua_State)
        {
            Lua.lua_pushnumber(lua_State, (double) GameRule.nCurrentLocalFlag);
            return 1;
        }

        public static int SCRIPT_SetValue(IntPtr state)
        {
            if (Lua.lua_gettop(state) < 1)
                return 0;

            Creature c = (Creature)Instance.m_obj;
            if (c == null)
            {
                Lua.lua_pushnumber(state, 0.0);
                return 1;
            }

            Player p = Instance.m_obj as Player;


            string str = Lua.lua_tostring(state, 1);

            string value = Lua.lua_tostring(state, 2);
            switch (str)
            {
                case "gold":
                    if(p != null)
                        p.m_nGold = Marshal.ToInt64(value);
                    break;

                case "race":
                    c.m_nRace = Marshal.ToInt32(value);
                    break;

                case "job":
                    c.m_nJob = Marshal.ToInt32(value);
                    break;

                case "job_level":
                    c.m_nJobLevel = Marshal.ToInt32(value);
                    break;

                case "job_depth":
                    if(p != null)
                        p.m_nJobDepth = Marshal.ToInt32(value);
                    break;

                case "max_hp":
                    c.m_nMaxHP = Marshal.ToInt32(value);
                    break;

                case "max_mp":
                    c.m_nMaxMP = Marshal.ToInt32(value);
                    break;

                case "hp":
                    c.m_nHP = Marshal.ToInt32(value);
                    break;

                case "mp":
                    c.m_fMP = Marshal.ToSingle(value);
                    break;

                case "x":
                    c.mv.x = Marshal.ToInt32(value);
                    break;

                case "y":
                    c.mv.y = Marshal.ToInt32(value);
                    break;

                case "layer":
                    c.m_layer = Marshal.ToByte(value);
                    break;

                case "job_0":
                    c.m_nPrevJobId[0] = Marshal.ToInt32(value);
                    break;
                case "job_1":
                    c.m_nPrevJobId[1] = Marshal.ToInt32(value);
                    break;
                case "job_2":
                    c.m_nPrevJobId[2] = Marshal.ToInt32(value);
                    break;

                case "jlv_0":
                    c.m_nPrevJobLevel[0] = Marshal.ToInt32(value);
                    break;
                case "jlv_1":
                    c.m_nPrevJobLevel[1] = Marshal.ToInt32(value);
                    break;
                case "jlv_2":
                    c.m_nPrevJobLevel[2] = Marshal.ToInt32(value);
                    break;

                case "stamina":
                    if (p != null)
                        p.m_nStamina = Marshal.ToInt32(value);
                    break;
                
                case "tp":
                    if (p != null)
                        p.m_nTP = Marshal.ToInt32(value);
                    break;
                case "chaos":
                    if (p != null)
                        p.m_nChaos = Marshal.ToInt32(value);
                    break;

                default:
                    Globals.Log.Error("SCRIPT_SetValue unknown field: {0}, value: {1}", str,value);
                    break;
            }


            if (p != null)
                p.onChangeProperty(str, value);

//            Lua.lua_pushnumber(state, ret);
            return 1;
        }

        public static int SCRIPT_GetProperChannelNo(IntPtr state)
        {
            if (Lua.lua_gettop(state) >= 1 )
            {
                int channel = ChannelManager.GetProperChannel((int)Lua.lua_tonumber(state, 1));
                Lua.lua_pushnumber(state, (double)channel);
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_GetProperChannelNo() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetLayerOfChannel(IntPtr state)
        {
            if (Lua.lua_gettop(state) >= 2 )
            {
                int channel_id = (int)Lua.lua_tonumber(state, 1);
                int channel_num = (int)Lua.lua_tonumber(state, 2);
                byte proper = ChannelManager.GetLayerOfChannel(channel_id, channel_num);
                Lua.lua_pushnumber(state, (double)proper);
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_GetUserCount() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_SetPlayerFlag(IntPtr state)
        {
            Player p = Instance.m_obj as Player;
            if (p == null)
            {
                Lua.lua_pushnumber(state, 0.0);
                return 1;
            }

            int top = Lua.lua_gettop(state);
            if (top >= 2)
            {
                string s1 = Lua.lua_tostring(state, top);
                string s2 = Lua.lua_tostring(state, top-1);
                p.SetFlag(s2, s1);
            }
            return 0;
        }

        public static int SCRIPT_RemovePlayerFlag(IntPtr state)
        {
            Player p = Instance.m_obj as Player;
            if (p == null)
            {
                Lua.lua_pushnumber(state, 0.0);
                return 1;
            }

            int top = Lua.lua_gettop(state);
            if (top >= 2)
            {
                string s1 = Lua.lua_tostring(state, top);
                p.RemoveFlag(s1);
            }
            return 0;
        }

        public static int SCRIPT_GetPlayerFlag(IntPtr state)
        {
            int result;

            Player player = Instance.m_obj as Player;
            if (player == null)
            {
                Lua.lua_pushnumber(state, 0.0);
                return 1;
            }

            int nArgCnt = Lua.lua_gettop(state);
            if (nArgCnt >= 1 )
            {
                string fname = Lua.lua_tostring(state,1);
                string value = player.GetFlag(fname);

                Double fval;
                bool isNum = Double.TryParse(value, System.Globalization.NumberStyles.Any, System.Globalization.NumberFormatInfo.InvariantInfo, out fval);
                if(nArgCnt >= 2)
                {
                    if(Lua.lua_isnumber(state,2) != 0)
                    {
                        if (isNum)
                        {
                            Lua.lua_pushnumber(state, fval);
                        }
                        else
                        {
                            Lua.lua_pushnumber(state, Lua.lua_tonumber(state,2));
                        }
                    }
                    else
                    {
                        if (isNum)
                        {
                            Lua.lua_pushstring(state, Lua.lua_tostring(state, 2));
                        }
                        else
                        {
                            Lua.lua_pushstring(state, value);
                        }
                    }
                }
                else
                {
                    if (isNum)
                    {
                        Lua.lua_pushnumber(state, fval);
                    }
                    else
                    {
                        Lua.lua_pushstring(state, value);
                    }
                }
                result = 1;
            }
            else
            {
                result = 0;
            }
            return result;
        }

        public static int SCRIPT_Conv(IntPtr state)
        {
            int result;
            bool v5; // sf@5

            int top = Lua.lua_gettop(state);
            if (top >= 1 && top % 2 == 1 && Lua.lua_isstring(state, 1) != 0)
            {
                int v6 = top - 1;
                v5 = top - 1 < 0;

                int count = 1;
                string res = "";
//                 if (!(v5 ^ v6) )
//                 {
                    do
                    {
                        if (count != 1 )
                            res += '\v';
                        res += Lua.lua_tostring(state, count);
                        ++count;
                    }
                    while (count <= top);
//                }
                Lua.lua_pushstring(state, res);
                result = 1;
            }
            else
            {
                result = 0;
            }
            return result;
        }

        public static int SCRIPT_Message(IntPtr state)
        {
            Player p = Instance.m_obj as Player;
            if (p == null)
                return 1;

            int top = Lua.lua_gettop(state);
            if (top >= 1 )
            {
                string str = Lua.lua_tostring(state, top);
                Messages.SendChatMessage(false, 40, "@SCRIPT", p, str, (uint)str.Length);
            }
            return 0;
        }

        public static int SCRIPT_SetEnv(IntPtr state)
        {
            int result = 0;
            if (Lua.lua_gettop(state) >= 2 )
            {
                string s1 = Lua.lua_tostring(state,2);
                string s2 = Lua.lua_tostring(state,1);
//                XEnvStruct::Set(s2,s1);
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_SetEnv() : invalid argument");
                result = 1;
            }
            return result;
        }

        public static int SCRIPT_GetEnv(IntPtr state)
        {
            if (Lua.lua_gettop(state) >= 1)
            {
                string s1 = Lua.lua_tostring(state,1);

                switch(s1)
                {
                    case "game.use_auto_trap":
                        Lua.lua_pushnumber(state, 0.0);
                        break;

                    case "game.cash_usable_server":
                        Lua.lua_pushnumber(state, 1.0);
                        break;

                    default:
                        Lua.lua_pushnumber(state, 0.0);
                        Globals.Log.Error("SCRIPT_GetEnv() : unknown env variable: "+s1);
                        break;


                }
//                 string s2 = XEnvStruct::GetString(s1,"<NULL>");
// 
//                 v11 = atof(v10);
//                 if ( 0.0 != v11 )
//                     goto LABEL_21;
//                 if ( *(_DWORD *)(v1 - 24) != 1 )
//                     goto LABEL_22;
//                 v12 = *(_DWORD *)(v1 - 40);
//                 if ( *(_DWORD *)(v1 - 20) < 0x10u )
//                     v12 = v1 - 40;
//                 if ( *(_BYTE *)v12 == 48 )
//                 {
//         LABEL_21:
//                     Lua.lua_pushnumber(state, v11);
//                 }
//                 else
//                 {
//         LABEL_22:
//                     v13 = *(const char **)(v1 - 40);
//                     if ( *(_DWORD *)(v1 - 20) < 0x10u )
//                         v13 = (const char *)(v1 - 40);
//                     Lua.lua_pushstring(state, v13);
//                 }
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_GetEnv() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_OpenPopup(IntPtr state)
        {
            int nArgCnt;
            bool bIsRequireOnetimePassword;
            string szUrl;
            string szOnetimePassword = "";

            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            nArgCnt = Lua.lua_gettop(state);
            if (nArgCnt >= 3 && Lua.lua_isnumber(state, nArgCnt) != 0)
            {
                bIsRequireOnetimePassword = (bool)(Lua.lua_tonumber(state, nArgCnt - 1) != 0.0);
                
                if (bIsRequireOnetimePassword)
                {
                    szOnetimePassword = String.Format("?server={0}&id={1}", GameRule.szServerName, player.GetAccountID());

                    int one_time_key = Globals.GetRandomInt32() % 0xFFFFFF;
                    szOnetimePassword += GameRule.AppendOnetimePassword(one_time_key, player.GetSID(), player.GetAccountID());
                    GameDBManager.Instance.Push(new DB_UpdateOneTimePassword(player.GetSID(),one_time_key));
                }
                szUrl = GameRule.GetString(Lua.lua_tostring(state,1),"");

                if (bIsRequireOnetimePassword)
                    szUrl += szOnetimePassword;
                for (int i = 2; i < nArgCnt - 1; ++i )
                {
                    szUrl += "|";
                    szUrl += GameRule.GetString(Lua.lua_tostring(state, i), "");
                    if (bIsRequireOnetimePassword)
                        szUrl += szOnetimePassword;
                }
                Messages.SendOpenUrl(player, szUrl, Lua.lua_tonumber(state, nArgCnt) != 0.0, 0, 0);
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_OpenPopup() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetServerCategory(IntPtr state)
        {
            int result = 0;
            
            result = ((GameRule.GetInt("game.ServiceServer", 0) != 0) ? 1 : 0) << 29;
            result = result | (((GameRule.GetInt("game.PKServer", 0) != 0) ? 1 : 0) << 28);
            result = result + GameRule.GetInt("auth.server_idx", 0);
            Lua.lua_pushnumber(state, (double) result);
            return 1;
        }

        public static int SCRIPT_SetCurrentLocationId(IntPtr state)
        {
            if (Lua.lua_gettop(state) >= 1 )
                GameContent.g_currentLocationId = (int)Lua.lua_tonumber(state, 1);
            return 0;
        }

        public static int SCRIPT_AddRespawnInfo(IntPtr state)
        {
            int result;
            int n = Lua.lua_gettop(state);
            if ( n >= 9
              && Lua.lua_isnumber(state, 1) != 0
              && Lua.lua_isnumber(state, 2) != 0
              && Lua.lua_isnumber(state, 3) != 0
              && Lua.lua_isnumber(state, 4) != 0
              && Lua.lua_isnumber(state, 5) != 0
              && Lua.lua_isnumber(state, 6) != 0
              && Lua.lua_isnumber(state, 7) != 0
              && Lua.lua_isnumber(state, 8) != 0
              && Lua.lua_isnumber(state, 9) != 0)
            {
                uint id = (uint) Lua.lua_tonumber(state, 1);
                uint interval = (uint) Lua.lua_tonumber(state, 2);
                float left = (float) Lua.lua_tonumber(state, 3);
                float top = (float) Lua.lua_tonumber(state, 4);
                float right = (float) Lua.lua_tonumber(state, 5);
                float bottom = (float) Lua.lua_tonumber(state, 6);
                uint monster_id = (uint) Lua.lua_tonumber(state, 7);
                uint max_num = (uint) Lua.lua_tonumber(state, 8);
                uint inc = (uint) Lua.lua_tonumber(state, 9);
                int wander_id = 0;
                if ( n > 9 )
                {
                    if (Lua.lua_isnumber(state, 10) != 0)
                    {
                        wander_id = 0;// (int)Lua.lua_tonumber(state, 10);
                    }
                }
                GameContent.MonsterRespawnInfo ri = new GameContent.MonsterRespawnInfo(id, interval, left, top, right, bottom, monster_id, max_num, inc, true, wander_id);
                GameContent.RegisterMonsterRespawnInfo(ri);
                result = 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddRespawnInfo() : invalid argument");
                result = 1;
            }
            return result;
        }

        public static int SCRIPT_AddDungeonGuardianRespawnInfo(IntPtr state)
        {
//             if (Lua.lua_gettop(state) >= 1)
//                 GameContent.g_currentLocationId = (int)Lua.lua_tonumber(state, 1);
            return 0;
        }

        public static int SCRIPT_AddDungeonEnvironmentalGuardianRespawnInfo(IntPtr state)
        {
//             if (Lua.lua_gettop(state) >= 1)
//                 GameContent.g_currentLocationId = (int)Lua.lua_tonumber(state, 1);
            return 0;
        }

        public static int SCRIPT_AddRareMobRespawnInfo(IntPtr state)
        {
            int result;
            int n = Lua.lua_gettop(state);
            if (n >= 7
              && Lua.lua_isnumber(state, 1) != 0
              && Lua.lua_isnumber(state, 2) != 0
              && Lua.lua_isnumber(state, 3) != 0
              && Lua.lua_isnumber(state, 4) != 0
              && Lua.lua_isnumber(state, 5) != 0
              && Lua.lua_isnumber(state, 6) != 0
              && Lua.lua_isnumber(state, 7) != 0)
            {
                uint id = (uint)Lua.lua_tonumber(state, 1);
                uint interval = (uint)Lua.lua_tonumber(state, 2);
                float left = (float)Lua.lua_tonumber(state, 3);
                float top = (float)Lua.lua_tonumber(state, 4);
                float right = left+1;
                float bottom = top+1;
                uint monster_id = (uint)Lua.lua_tonumber(state, 5);
                uint max_num = (uint)Lua.lua_tonumber(state, 6);
                uint inc = max_num;
                bool is_wander = (uint)Lua.lua_tonumber(state, 7) != 0;
                int wander_id = 0;
                if (n > 7)
                {
                    if (Lua.lua_isnumber(state, 8) != 0)
                    {
                        wander_id = (int)Lua.lua_tonumber(state, 8);
                    }
                }
                GameContent.MonsterRespawnInfo ri = new GameContent.MonsterRespawnInfo(id, interval, left, top, right, bottom, monster_id, max_num, inc, is_wander, wander_id);

                GameContent.RegisterMonsterRespawnInfo(ri);
                result = 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddRareMobRespawnInfo() : invalid argument");
                result = 1;
            }
            return result;
        }

        public static int SCRIPT_AddRoamingMobRespawnInfo(IntPtr state)
        {
            int result;

            GameContent.RoamingCreatureRespawnInfo info = new GameContent.RoamingCreatureRespawnInfo();
            int nRoamingID;
            float nDistance;
            int n;

            n = Lua.lua_gettop(state);
            if ( n >= 4
              && Lua.lua_isnumber(state, 1) != 0
              && Lua.lua_isnumber(state, 2) != 0
              && Lua.lua_isnumber(state, 3) != 0
              && Lua.lua_isnumber(state, 4) != 0
              && (n < 5 || Lua.lua_isnumber(state, 5) != 0) )
            {
                nRoamingID = (int)Lua.lua_tonumber(state, 1);
                nDistance = (float)Lua.lua_tonumber(state, 4) * 12.0f;
                if ( n < 5 )
                    info.m_nRespawnInterval = 0;
                else
                    info.m_nRespawnInterval = (uint)Lua.lua_tonumber(state, 5) * 100;
                info.m_eCreatureType = 0;
                info.m_nCreatureID = (int)Lua.lua_tonumber(state, 2);
                info.m_nDistance = nDistance;
                info.m_nAngle = (int)Lua.lua_tonumber(state, 3);
                RoamingManager.Instance.AddRoamingCreatureRespawnInfo(nRoamingID, info);
                result = 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddRoamingMobRespawnInfo() : invalid argument");
                result = 1;
            }
            return result;
        }

        public static int SCRIPT_AddRaidRespawnInfo(IntPtr state)
        {
//             if (Lua.lua_gettop(state) >= 1)
//                 GameContent.g_currentLocationId = (int)Lua.lua_tonumber(state, 1);
            return 0;
        }

        public static int SCRIPT_AddRaidRareMobRespawnInfo(IntPtr state)
        {
//             if (Lua.lua_gettop(state) >= 1)
//                 GameContent.g_currentLocationId = (int)Lua.lua_tonumber(state, 1);
            return 0;
        }

        public static int SCRIPT_DialogTitle(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            if (Lua.lua_gettop(state) >= 1 )
            {
                player.SetDialogTitle(Lua.lua_tostring(state,1), 0);
            }
            return 0;
        }

        public static int SCRIPT_DialogText(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            if (Lua.lua_gettop(state) >= 1 )
            {
                player.SetDialogText(Lua.lua_tostring(state,1));
                GameContent.ShowQuestMenu(player);
            }
            return 0;
        }

        public static int SCRIPT_DialogMenu(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            if (Lua.lua_gettop(state) >= 2 )
            {
                player.AddDialogMenu(Lua.lua_tostring(state,1),Lua.lua_tostring(state,2));
            }
            return 0;
        }

        public static int SCRIPT_DialogShow(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;
            player.ShowDialog();
            return 0;
        }


        public static int SCRIPT_GetQuestProgress(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                int p = player.GetQuestProgress((int)Lua.lua_tonumber(state, 1));
                Lua.lua_pushnumber(state, (double) p);
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddRespawnInfo() : invalid argument");
                return 1;
            }
            return 1;
        }

        public static int SCRIPT_DialogTextWithoutQuest(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            if (Lua.lua_gettop(state) >= 1)
            {
                player.SetDialogText(Lua.lua_tostring(state,1));
            }
            return 0;
        }

        public static int SCRIPT_QuestInfo(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;
            int code;


            int nt = Lua.lua_gettop(state);
            if (nt >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                code = (int)Lua.lua_tonumber(state, 1);
                if (nt >= 2 )
                {
                    Messages.SendQuestInformation(player, code, (int)Lua.lua_tonumber(state, 2));
                }
                else
                {
                    Messages.SendQuestInformation(player, code, 0);
                }
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_QuestInfo() : invalid argument");
                return 1;
            }
            return 0;
        }

        public static int SCRIPT_StartQuest(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            if (player == null)
                return 1;

            if (Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                if (player.StartQuest((int)Lua.lua_tonumber(state, 1), (int)Lua.lua_tonumber(state, 2), false))
                    Lua.lua_pushnumber(state, 1.0);
                else
                    Lua.lua_pushnumber(state, 0.0);

                return 0;
            }
            Lua.lua_pushnumber(state, 0.0);
            Error("SCRIPT_StartQuest() : invalid argument");
            return 1;
        }

        public static int SCRIPT_WarpToRevivePosition(IntPtr state)
        {
            ArPosition pos; // ptr -80 -50h
            ArPosition nearest_pos;//     = ArPosition ptr -40h
            ArPosition revive_pos;//      = ArPosition ptr -48 -30h
//.text:004C0B4F pit             = StructPlayer::iterator ptr -20h
            int dungeon_id;//      = dword ptr -18h
            float fAngle;//          = dword ptr -14h
            byte layer;//           = byte ptr -10h
//.text:004C0B4F L               = dword ptr  8
            int current_channel;
            int revive_channel;

//Data           :   ebp Relative, [FFFFFFEC], Local, Type: int, current_channel -32 -20

            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                if (player.IsInBattleField())
                    return 0;

                revive_pos = player.GetLastTownPosition();
                pos = new ArPosition(player.mv);

                layer = 0;

                current_channel = ChannelManager.GetChannelId(pos.x,pos.y);
                revive_channel = ChannelManager.GetChannelId(revive_pos.x, revive_pos.y);
                dungeon_id = DungeonManager.Instance.GetDungeonID(pos.x, pos.y);

                if (dungeon_id == 0 || player.m_layer == 0)
                {
                    if (revive_channel != 0 && ChannelManager.GetChannelType(revive_channel) == 1)
                    {
                        if (current_channel != revive_channel)
                        {
                            layer = ChannelManager.GetProperLayer(revive_pos.x, revive_pos.y);
                        }
                        else
                        {
                            layer = player.m_layer;
                        }
                    }
                    else if (player.m_layer == 0)
                    {
                        layer = player.m_layer;
                    }
                }
                else {
                    // here we know that player layer definitely isn't 0
                    // check to see if we are in a siege or time attack
                    if (dungeon_id == 0 || ChannelManager.GetChannelType(dungeon_id) != 2 || player.m_nPartyId == 0 ||
                          PartyManager.Instance.GetAttackTeamGuildID(player.m_nPartyId) == 0)
                    {
                        // neither
                        layer = 0;
                    }
                    else
                    {
                        // we are
                        if (player.m_layer == 1)
                        {
                            // in a siege
                            nearest_pos = DungeonManager.Instance.GetNearestTacticalPosition(dungeon_id, PartyManager.Instance.GetAttackTeamGuildID(player.m_nPartyId), pos);
                            // if the following is true then something is very wrong, send back to town and be done with it
                            if (0.0f != nearest_pos.x && 0.0f != nearest_pos.y)
                            {
                                fAngle = (float)Globals.GetRandomInt32(0, 359) * 3.141592741012573f / 180.0f;
                                nearest_pos.x += ((float)Math.Sin(fAngle) * 48.0f);
                                nearest_pos.y += ((float)Math.Cos(fAngle) * 48.0f);
                                revive_pos = nearest_pos;
                                layer = player.m_layer;
                            }
                        }
                        else
                        {
                            // in a time attack
                            revive_pos = DungeonManager.Instance.GetRaidStartPosition(dungeon_id);
                            layer = player.m_layer;
                        }
                    }
                }

                player.PendWarp((int)revive_pos.x, (int)revive_pos.y, layer);
                player.SetMove(player.GetCurrentPosition(Globals.GetArTime()), 0, 0);

                RappelzServer.Instance.SetObjectPriority(player, SchedulerObject.Priority.Highest);
            }
            else
            {
                Error("SCRIPT_WarpToRevivePosition() : invalid name");
            }

            return 0;
        }

        public static int SCRIPT_EndQuest(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                if (player == null)
                {
                    return 0;
                }
                bool bForce = false;
                if (Lua.lua_gettop(state) >= 3 && Lua.lua_isnumber(state, 3) != 0)
                {
                    bForce = (int)Lua.lua_tonumber(state, 3) != 0;
                }
                if (!player.EndQuest((int)Lua.lua_tonumber(state, 1), (int)Lua.lua_tonumber(state, 2), bForce))
                {
                    Lua.lua_pushnumber(state, 0.0);
                    return 1;
                }
                Lua.lua_pushnumber(state, 1.0);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_EndQuest() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_ShowStorage(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                if (player.Connection != null && player.Connection.Socket.Connected)
                {
                    if (player.Connection.Tag != null)
                    {
                        if (GameRule.bUseSecurityNoForStorage && (GameRule.bCheckStorageSecurityAlways || player.Connection.Tag.bStorageSecurityCheck))
                            player.RequestSecurityNo(1);
                        else
                            player.OpenStorage();
                    }
                }
            }

            return 0;
        }

        public static int SCRIPT_Warp(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            float x = 0;
            float y = 0;
            byte layer = 0;

            int cnt = Lua.lua_gettop(state);
            if (cnt < 2)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_Warp() : invalid argument");
                return 1;
            }
                
            x = (float)Lua.lua_tonumber(state, 1);
            y = (float)Lua.lua_tonumber(state, 2);

            if (x < 0.0f || GameContent.g_nMapWidth < x || y < 0.0f || GameContent.g_nMapHeight < y)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_Warp() : invalid argument");
                return 1;
            }
            if (cnt > 3 && Lua.lua_isnumber(state, 3) != 0 && Lua.lua_isnumber(state, 4) != 0)
            {
                layer = ChannelManager.GetLayerOfChannel((int)Lua.lua_tonumber(state, 3), (int)Lua.lua_tonumber(state, 4));
            }
            else
            {
                if (cnt > 2 && Lua.lua_isnumber(state, 3) != 0)
                {
                    layer = (byte) Lua.lua_tonumber(state, 3);
                }
                else
                {
                    if (player != null && ChannelManager.GetChannelId(player.m_layer) == ChannelManager.GetChannelId(x,y))
                        layer = player.m_layer;
                    else
                        layer = ChannelManager.GetProperLayer(x,y);
                }
            }

            if (player == null)
            {
                Lua.lua_pushstring(state, "invalid name");
                Error("SCRIPT_Warp() : invalid name");
                return 1;
            }
            player.PendWarp((int)x,(int)y,layer);
            RappelzServer.Instance.SetObjectPriority(player, SchedulerObject.Priority.Highest);
            return 0;
        }

        public static int SCRIPT_SendGoldChaosUpdate(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                Messages.SendGoldChaosUpdateMsg(player);
                Lua.lua_pushnumber(state, 1.0);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_SendUpdateGoldChaos() : invalid name");
            }
            return 1;
        }

        public static int SCRIPT_SavePlayer(IntPtr state)
        {
            int r;

            r = 1;
            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                player.Save(false);
                r = 0;
            }
            else
            {
                Lua.lua_pushstring(state, "Can't find player");
                Error("SCRIPT_SavePlayer() : Can't find player");
            }
            return r;
        }

        public static int SCRIPT_GetNPCId(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                uint npc_id = player.GetLastContactLong("npc");
                if (npc_id != 0)
                {
                    NPC npc = NPC.get(npc_id) as NPC;
                    if (npc != null && npc.IsNPC())
                    {
                        Lua.lua_pushnumber(state, npc.m_BaseInfo.id);
                        return 1;
                    }
                }
                Lua.lua_pushnumber(state, 0.0f);
                return 1;
            }
            return 0;
        }

        public static int SCRIPT_FindItem(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                if (player != null)
                {
                    Item pItem = player.FindItemByCode((int)Lua.lua_tonumber(state,1));
                    if (pItem != null)
                        Lua.lua_pushnumber(state, pItem.m_Instance.nCount);

                    else
                        Lua.lua_pushnumber(state, 0.0);
                }
                else
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_FindItem() : invalid argument");
                }
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_FindItem() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetStateLevel(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            Creature cr = null;

            int top = Lua.lua_gettop(state);
            if (top >= 1)
            {
                int nStateID = (int)Lua.lua_tonumber(state, 1);
                if (top == 2 && Lua.lua_isnumber(state, 2) != 0)
                {
                    cr = GameObject.raw_get((uint)Lua.lua_tonumber(state, 2)) as Creature;
                }
                else
                {
                    cr = player;
                }
                if (cr != null)
                {
                    State s = cr.GetState((State.StateCode)nStateID);
                    if (s != null)
                    {
                        Lua.lua_pushnumber(state, s.GetLevel());
                    }
                    else
                    {
                        Lua.lua_pushnumber(state, 0.0);
                    }
                    return 1;
                }
            }
            return 0;
        }

        public static int SCRIPT_ShowMarket(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string str;
            MarketInfo market;

            if (Lua.lua_gettop(state) >= 1 )
            {
                if (player != null)
                {
                    str = Lua.lua_tostring(state, 1);
                    market = GameContent.GetMarketInfo(str);

                    if (market != null)
                    {
                        Messages.SendMarketInfo(player, player.GetLastContactLong("npc"), market);
                    }
                }
            }
            return 0;
        }

        public static int SCRIPT_WarpToDungeon(IntPtr state)
        {
            ArPosition startPosition;       //   = ArPosition ptr -54h
//            ArPosition defencePositon;      //
// .text:004C0EED vClosedDungeons = std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > > ptr -44h
// .text:004C0EED pit             = StructPlayer::iterator ptr -34h
            float x;                        // -40  -28h
            float y;                        // -28  -18h
            byte layer;                     // -20  -14h
            int dungeon_id;                 // -16  -10h
// .text:004C0EED L               = dword ptr  8
// 
// Data           :   ebp Relative, [00000008], Param, Type: struct lua_State *, L
// Data           :   ebp Relative, [FFFFFFCC], Local, Type: struct StructPlayer::iterator, pit
// Data           :   ebp Relative, [FFFFFFEC], Local, Type: unsigned char, layer
// Data           :   ebp Relative, [FFFFFFF0], Local, Type: int, dungeon_id
// Data           :   ebp Relative, [FFFFFFD8], Local, Type: float, x
// Data           :   ebp Relative, [FFFFFFE8], Local, Type: float, y
// Data           :   ebp Relative, [FFFFFFAC], Local, Type: struct ArPosition, startPosition
// Data           :   ebp Relative, [FFFFFFBC], Local, Type: class std::vector<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >, vClosedDungeons
// Data           :   ebp Relative, [FFFFFFD4], Local, Type: class std::_Vector_iterator<std::basic_string<char,std::char_traits<char>,std::allocator<char> >,std::allocator<std::basic_string<char,std::char_traits<char>,std::allocator<char> > > >, it
// Data           :   ebp Relative, [FFFFFFDC], Local, Type: struct ArPosition, defencePosition
// Data           :   ebp Relative, [FFFFFFDC], Local, Type: struct ArPosition, startPosition


            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) < 1 || Lua.lua_isnumber(state, 1) == 0)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_WarpToDungeon() : invalid argument");
                return 1;
            }
            dungeon_id = (int) Lua.lua_tonumber(state, 1);

            if (player == null)
            {
                Lua.lua_pushstring(state, "invalid name");
                Error("SCRIPT_WarpToDungeon() : invalid name");
                return 1;
            }

            // TODO: Closed Dungeons
//            v7 = XEnvStruct::GetString(v6, (v1 - 112), "game.closed_dungeons", &unk_5F42BB);
//            XStringUtil::Split(v9, (v1 - 68), "|", 1);
//             if(closed)
//             {
//                 Lua.lua_pushstring(state, "dungeon closed");
//                 return 1;
//             }

            if (DungeonManager.Instance.IsRestrictedToEnter(dungeon_id, player, false) != 0)
            {
                Messages.PrintfChatMessage(false, 20, "@NOTICE", player, "@563\v#@player_name@#\v%s", player.GetName());
                Lua.lua_pushstring(state, "level limit");
                return 1;
            }

            layer = 0;
            startPosition = DungeonManager.Instance.GetRaidStartPosition(dungeon_id);

            x = startPosition.x;
            y = startPosition.y;
            if (player.m_nPartyId != 0)
            {
                if (PartyManager.Instance.IsAttackTeamParty(player.m_nPartyId))
                {
                    int attackGuildId = PartyManager.Instance.GetAttackTeamGuildID(player.m_nPartyId);

                    if (GuildManager.Instance.GetRaidDungeonID(attackGuildId) == dungeon_id)
                    {
                        if (DungeonManager.Instance.IsEnterableSiegeDungeon(dungeon_id, attackGuildId))
                        {
                            if (PartyManager.Instance.GetPartyType(player.m_nPartyId) == PartyManager.PartyType.SeigeAttackTeam)
                            {
                                int ownGuildId = DungeonManager.Instance.GetOwnGuildID(dungeon_id);
                                if (ownGuildId == attackGuildId)
                                {
                                    startPosition = DungeonManager.Instance.GetSiegeDefencePosition(dungeon_id);
                                }
                                else
                                {
                                    startPosition = DungeonManager.Instance.GetSiegeStartPosition(dungeon_id);
                                }
                                layer = 1;
                                x = startPosition.x;
                                y = startPosition.y;
                            }
                        }
                        else
                        {
                            if (DungeonManager.Instance.IsDungeonRaidTime(dungeon_id))
                            {
                                if (PartyManager.Instance.GetPartyType(player.m_nPartyId) == PartyManager.PartyType.RaidAttackTeam)
                                {
                                    layer = DungeonManager.Instance.GetRaidDungeonLayer(dungeon_id, attackGuildId);
                                    if (layer == 0)
                                    {
                                        if (!DungeonManager.Instance.IsRaidBegin(dungeon_id, attackGuildId))
                                        {
                                            if (DungeonManager.Instance.GetOwnGuildID(dungeon_id) != attackGuildId)
                                            {
                                                if (GuildManager.Instance.IsRaidLeader(attackGuildId, player.GetName()))
                                                {
                                                    player.SetSpecialDialogMenu("begin_dungeon_raid");
                                                    player.m_bNonNPCDialog = true;
                                                    Messages.SendWindowMessage(player,"dungeon_raid_confirm_window",player.GetName(),"begin_dungeon_raid");
                                                    return 0;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
//                    if (layer >= 256)
//                        layer = 0;
            player.m_StatusFlag |= Creature.StatusFlags.Invincible;
            startPosition = player.GetCurrentPosition(Globals.GetArTime());
            player.SetMove(startPosition,0,0);
            player.PendWarp((int)x, (int)y, layer);
            RappelzServer.Instance.SetObjectPriority(player, SchedulerObject.Priority.Highest);
            return 0;
        }

        public static int SCRIPT_GetOwnDungeonID(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0;

            if (player != null)
            {
                int guildId = player.m_nGuildId;

                if (player.m_nGuildId != 0)
                {
                    int allianceId = GuildManager.Instance.GetAllianceID(player.m_nGuildId);
                    if (allianceId != 0)
                        guildId = GuildManager.Instance.GetAllianceLeaderGuildID(allianceId);

                    int raidId = GuildManager.Instance.GetRaidDungeonID(guildId);
                    if (raidId != 0 && DungeonManager.Instance.GetOwnGuildID(raidId) == guildId)
                        res = raidId;
                }

                Lua.lua_pushnumber(state, res);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_GetOwnDungeonID() : invalid name");
            }
            return 1;
        }

        public static int SCRIPT_GetSiegeDungeonID(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            double res = 0;

            if (player != null)
            {
                int guildId = player.m_nGuildId;

                if (player.m_nGuildId != 0)
                {
                    int allianceId = GuildManager.Instance.GetAllianceID(player.m_nGuildId);
                    if (allianceId != 0)
                        guildId = GuildManager.Instance.GetAllianceLeaderGuildID(allianceId);

                    int raidId = GuildManager.Instance.GetRaidDungeonID(guildId);
                    if (raidId != 0 && DungeonManager.Instance.GetRaidGuildID(raidId) == guildId)
                        res = raidId;
                }
                Lua.lua_pushnumber(state, res);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_GetSiegeDungeonID() : invalid name");
            }
            return 1;
        }

        public static int SCRIPT_GetWearItemHandle(IntPtr state)
        {
            double res = 0.0;

            Player player = Instance.m_obj as Player;

            int top = Lua.lua_gettop(state);
            int type = -22;
            Item pItem = null;
            if(top >= 1)
                type = (int)Lua.lua_tonumber(state, 1);
            
            if (player != null && type != -22)
                pItem = player.GetWornItem((ItemBase.ItemWearType)type);
            
            if(pItem != null)
            {
                res = pItem.m_hHandle;
                if (res < 0 )
                    res += 4294967296.0;
            }

            Lua.lua_pushnumber(state, res);
            return 1;
        }

        public static int SCRIPT_GetItemHandle(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0 && player != null)
            {
                Item pItem = player.FindItemByCode((int)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                {
                    res = pItem.m_hHandle;
                }
                Lua.lua_pushnumber(state, res);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_GetItemHandle() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetItemName(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem =Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                {
                    Lua.lua_pushstring(state, pItem.GetName());
                }
                else
                {
                    Lua.lua_pushstring(state, "");
                }
            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemName() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_GetItemCode(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.m_Instance.Code;

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemCode() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_SetItemLevel(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                if (player != null)
                {
                    Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));

                    if (pItem != null
                        && pItem.m_Instance.OwnerHandle == player.m_hHandle
                        && pItem.m_Instance.nWearInfo != ItemBase.ItemWearType.WearNone
                        || player.m_nPermission != 0)
                    {
                        int newLevel = (int)Lua.lua_tonumber(state, 2);
                        pItem.m_Instance.nLevel = newLevel;
                        pItem.m_bIsNeedUpdateToDB = true;
                        Lua.lua_pushnumber(state, newLevel);
                        player.UpdateQuestStatusByItemUpgrade();
                        Messages.SendItemMessage(player, pItem);
                        if (pItem.m_Instance.nWearInfo != ItemBase.ItemWearType.WearNone)
                        {
                            if (pItem.m_Instance.OwnSummonHandle != 0)
                            {
                                Summon s = Summon.get(pItem.m_Instance.OwnSummonHandle) as Summon;
                                if (s != null)
                                    s.CalculateStat();
                            }
                            else
                            {
                                player.CalculateStat();
                            }
                        }
                    }
                    else
                    {
                        Lua.lua_pushnumber(state, 0.0);
                    }
                }
                else
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_SetItemLevel() : invalid argument");
                }
            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_SetItemLevel() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetItemLevel(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.m_Instance.nLevel;

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemLevel() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_SetItemEnhance(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                if (player != null)
                {
                    Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));

                    if (pItem != null
                        && pItem.m_Instance.OwnerHandle == player.m_hHandle
                        && pItem.m_Instance.nWearInfo != ItemBase.ItemWearType.WearNone
                        || player.m_nPermission != 0)
                    {
                        int newLevel = (int)Lua.lua_tonumber(state, 2);
                        pItem.m_Instance.nEnhance = newLevel;
                        pItem.m_bIsNeedUpdateToDB = true;
                        Lua.lua_pushnumber(state, newLevel);
                        player.UpdateQuestStatusByItemUpgrade();
                        Messages.SendItemMessage(player, pItem);
                        if (pItem.m_Instance.nWearInfo != ItemBase.ItemWearType.WearNone)
                        {
                            if (pItem.m_Instance.OwnSummonHandle != 0)
                            {
                                Summon s = Summon.get(pItem.m_Instance.OwnSummonHandle) as Summon;
                                if (s != null)
                                    s.CalculateStat();
                            }
                            else
                            {
                                player.CalculateStat();
                            }
                        }
                    }
                    else
                    {
                        Lua.lua_pushnumber(state, 0.0);
                    }
                }
                else
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_SetItemEnhance() : invalid argument");
                }
            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_SetItemEnhance() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetItemEnhance(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.m_Instance.nEnhance;

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemEnhance() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_GetItemRank(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.GetItemRank();

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemRank() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_GetItemPrice(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.m_pItemBase.nPrice;

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemPrice() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_GetItemEndurance(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.m_Instance.nCurrentEndurance;

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemEndurance() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_SetItemEndurance(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                if (player != null)
                {
                    Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));

                    if (pItem != null
                        && pItem.m_Instance.OwnerHandle == player.m_hHandle
                        && pItem.m_Instance.nWearInfo != ItemBase.ItemWearType.WearNone
                        || player.m_nPermission != 0)
                    {
                        int newLevel = (int)Lua.lua_tonumber(state, 2);
                        pItem.SetCurrentEndurance(newLevel);
                        Messages.SendItemMessage(player, pItem);
                    }
                    else
                    {
                        Lua.lua_pushnumber(state, 0.0);
                    }
                }
                else
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_SetItemEndurance() : invalid argument");
                }
            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_SetItemEndurance() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_GetItemSocketCode(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                int socket_index = (int)Lua.lua_tonumber(state, 2);
                if (socket_index > 3)
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_GetItemSocketCode() : invalid argument");
                    return 1;
                }

                if(player == null)
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_GetItemSocketCode() : invalid argument");
                    return 1;
                }

                Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                if (pItem != null)
                    res = pItem.m_Instance.Socket[socket_index];

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemSocketCode() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_SetItemSocketCode(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0 && Lua.lua_isnumber(state, 3) != 0)
            {
                int socket_index = (int)Lua.lua_tonumber(state, 2);
                if (socket_index > 3 || player == null)
                {
                    Lua.lua_pushnumber(state, 0.0);
                    Error("SCRIPT_GetItemSocketCode() : invalid argument");
                    return 1;
                }

                int scode = (int)Lua.lua_tonumber(state, 3);
                ItemBaseServer isb = Item.GetItemBase(scode);
                if (isb.nCode == 0 || isb.nType != 8)
                {
                    Lua.lua_pushnumber(state, 0.0);
                    return 1;
                }

                if (player != null)
                {
                    Item pItem = Item.FindItem((uint)Lua.lua_tonumber(state,1));
                    if (pItem != null)
                    {
                        pItem.m_Instance.Socket[socket_index] = scode;
                        pItem.SetCurrentEndurance(isb.nEndurance + pItem.m_Instance.nCurrentEndurance);
                        Messages.SendItemMessage(player, pItem);
                    }
                    else
                    {
                        Lua.lua_pushnumber(state, 0.0);
                    }
                }
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_GetItemSocketCode() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_ItemName(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            string res = "";

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                ItemBaseServer ibs = Item.GetItemBase((int)Lua.lua_tonumber(state, 1));
                if (ibs != null)
                    res = GameContent.GetString(ibs.nNameId);

                Lua.lua_pushstring(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_ItemName() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_GetItemNameId(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 80.0;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                ItemBaseServer ibs = Item.GetItemBase((int)Lua.lua_tonumber(state, 1));
                if (ibs != null)
                    res = ibs.nNameId;

                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushstring(state, "");
                Error("SCRIPT_GetItemNameId() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_GetCreatureHandle(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;
            int top = Lua.lua_gettop(state);
            if (top < 1 || player == null)
                return 0;

            int slot = (int)Lua.lua_tonumber(state, top);
            if (slot <= 6)
            {
                Summon s = player.GetSummonAt(slot);
                if (s != null)
                    res = s.m_nSID;
            }
            Lua.lua_pushnumber(state, res);
            return 1;

        }


        public static int SCRIPT_GetCreatureValue(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            int result = 0;

            if (Lua.lua_gettop(state) >= 2)
            {
                if (player != null)
                {
                    string str = Lua.lua_tostring(state, 2);
                    int slot = (int)Lua.lua_tonumber(state, 1);
                    Summon s = player.GetSummon(slot);
                    result = 1;
                    if (s != null)
                    {
                        switch(str)
                        {
                            case "name":
                                Lua.lua_pushstring(state, s.GetName());
                                break;

                            case "evolution_depth":
                                Lua.lua_pushnumber(state, (double)s.m_nTransformLevel);
                                break;

                            case "level":
                                Lua.lua_pushnumber(state, (double)s.m_nLevel);
                                break;

                            case "job":
                                Lua.lua_pushnumber(state, (double)s.m_nJob);
                                break;

                            case "mp":
                                Lua.lua_pushnumber(state, (double)s.m_fMP);
                                break;

                            case "hp":
                                Lua.lua_pushnumber(state, (double)s.m_nHP);
                                break;

                            case "max_hp":
                                Lua.lua_pushnumber(state, (double)s.m_nMaxHP);
                                break;

                            case "max_mp":
                                Lua.lua_pushnumber(state, (double)s.m_nMaxMP);
                                break;

                            case "summon_state":
                                Lua.lua_pushnumber(state, (double)(s.m_bIsSummoned ? 1.0 : 0.0));
                                break;

                            default:
                                Error("SCRIPT_GetCreatureValue unknown field: {0}", str);
                                break;

                        }
                    }
                    else
                    {
                        Lua.lua_pushnumber(state, 0.0);
                    }
                }
            }
            return result;

        }

        public static int SCRIPT_SetCreatureValue(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 3 )
            {
                if (player != null)
                {
                    string szKey = Lua.lua_tostring(state, 2);
                    string szData = Lua.lua_tostring(state, 3);
                    int slot = (int)Lua.lua_tonumber(state, 1);
                    Summon s = player.GetSummon(slot);
                    if (s != null)
                    {
                        switch(szKey)
                        {
                            case "ev_1_ID":
                                s.m_nPrevJobId[0] = Marshal.ToInt32(szData);
                                break;
                            case "ev_2_ID":
                                s.m_nPrevJobId[1] = Marshal.ToInt32(szData);
                                break;
                            case "ev_3_ID":
                                s.m_nPrevJobId[2] = Marshal.ToInt32(szData);
                                break;
                            case "ev_1_level":
                                s.m_nPrevJobLevel[0] = Marshal.ToInt32(szData);
                                break;
                            case "ev_2_level":
                                s.m_nPrevJobLevel[1] = Marshal.ToInt32(szData);
                                break;
                            case "ev_3_level":
                                s.m_nPrevJobLevel[2] = Marshal.ToInt32(szData);
                                break;
                            case "hp":
                                s.m_nHP = Marshal.ToInt32(szData);
                                break;
                            case "mp":
                                s.m_fMP = Marshal.ToSingle(szData);
                                break;

                            default:
                                Error("SCRIPT_SetCreatureValue unknown field: {0},{1}", szKey, szData);
                                break;
                        }
                        if (s != null)
                            s.onChangeProperty(szKey, szData);
                    }
                }
            }
            return 0;


        }
        

        public static int SCRIPT_CreatureEvolution(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) < 1)
                return 0;

            if (player != null)
            {
                int slot = (int)Lua.lua_tonumber(state, 1);
                Summon s = player.GetSummon(slot);
                if(s != null)
                {
                    if (s.DoEvolution())
                        res = 1.0;
                    Lua.lua_pushnumber(state, res);
                    return 1;
                }
            }
            return 0;
        }

        public static int SCRIPT_Notice(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string szSender;
            string szString;

            int top = Lua.lua_gettop(state);
            szSender = "@NOTICE";
            szString = "";
            if (top < 1)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_Notice() : invalid argument");
                return 1;
            }
            else
            {
                szString = Lua.lua_tostring(state, 1);
                if (top == 2 )
                {
                    szSender = szString;
                    szString = Lua.lua_tostring(state, 2);
                }
                Messages.SendGlobalChatMessage(20, szSender, szString, 0);
            }
            return 0;
        }

        public static int SCRIPT_LocalNotice(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string szSender;
            string szString;

            int top = Lua.lua_gettop(state);
            szSender = "@NOTICE";
            szString = "";
            if (top < 1)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_LocalNotice() : invalid argument");
                return 1;
            }
            else
            {
                szString = Lua.lua_tostring(state, 1);
                if (top == 2)
                {
                    szSender = szString;
                    szString = Lua.lua_tostring(state, 2);
                }
                Messages.SendGlobalChatMessage(120, szSender, szString, 0);
            }
            return 0;
        }

        public static int SCRIPT_Announce(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string szSender;
            string szString;

            int top = Lua.lua_gettop(state);
            szSender = "@ANNOUNCE";
            szString = "";
            if (top < 1)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_Announce() : invalid argument");
                return 1;
            }
            else
            {
                szString = Lua.lua_tostring(state, 1);
                if (top == 2)
                {
                    szSender = szString;
                    szString = Lua.lua_tostring(state, 2);
                }
                Messages.SendGlobalChatMessage(21, szSender, szString, 0);
            }
            return 0;
        }

        public static int SCRIPT_Chat(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string szSender;
            string szString;

            int top = Lua.lua_gettop(state);
            if (top < 3)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_Notice() : invalid argument");
                return 1;
            }
            else
            {
                int type = (int)Lua.lua_tonumber(state, 1);
                szSender = Lua.lua_tostring(state, 2);
                szString = Lua.lua_tostring(state, 3);
                Messages.SendChatMessage(false,type, szSender, player, szString, 0);
            }
            return 0;
        }

        public static int SCRIPT_GChat(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string szSender;
            string szString;

            int top = Lua.lua_gettop(state);
            if (top < 3)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_Notice() : invalid argument");
                return 1;
            }
            else
            {
                int type = (int)Lua.lua_tonumber(state, 1);
                szSender = Lua.lua_tostring(state, 2);
                szString = Lua.lua_tostring(state, 3);
                Messages.SendGlobalChatMessage(type, szSender, szString, 0);
            }
            return 0;
        }

        public static int SCRIPT_DeleteItem(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 2)
            {
                if (player != null)
                {
                    Item di = Item.FindItem((uint)Lua.lua_tonumber(state, 1));
                    if (di != null)
                    {
//                         v7 = di.m_Instance.nEnhance;
//                         *(v1 - 24) = di.m_Instance.nLevel;
//                         *(v1 - 16) = di.m_Instance.Code;
//                         *(v1 - 60) = LODWORD(di.m_Instance.nCount);
//                         *(v1 - 56) = HIDWORD(di.m_Instance.nCount);
//                         *(v1 - 52) = LODWORD(di.m_Instance.UID);
//                         *(v1 - 48) = HIDWORD(di.m_Instance.UID);
                        bool r = player.EraseItem(di, (long)Lua.lua_tonumber(state, 2));
//                         v9 = *(v3 + 112);
                        if (r)
                         {
//                             v10 = v9;
//                             v11 = *(v3 + 108);
//                             *(v1 - 68) = v10;
//                             *(v1 - 64) = HIDWORD(v10);
//                             *(v1 - 76) = v11;
//                             LODWORD(v10) = *(v1 - 16);
//                             *(v1 - 84) = 0;
//                             *(v1 - 80) = 0;
//                             *(v1 - 72) = v11 >> 32;
//                             v10 = v10;
//                             *(v1 - 20) = v10;
//                             LODWORD(v10) = *(v1 - 24) + 100 * v7;
//                             *(v1 - 16) = HIDWORD(v10);
//                             v10 = v10;
//                             *(v1 - 92) = v10;
//                             LODWORD(v10) = *v3;
//                             *(v1 - 88) = HIDWORD(v10);
//                             v12 = (*(v10 + 64))(v3);
//                             *(v1 - 100) = v12;
//                             *(v1 - 96) = v12 >> 32;
//                             v13 = StructPlayer::GetAccountID(v3);
//                             *(v1 - 108) = v13;
//                             *(v1 - 28) = *(v3 + 4200);
//                             *(v1 - 24) = *(v3 + 4204);
//                             LODWORD(v13) = *v3;
//                             *(v1 - 104) = HIDWORD(v13);
//                             v14 = (*(v13 + 60))(v3);
//                             v15 = StructPlayer::GetAccountName(v3);
//                             LOG::Log11N4S(
//                                 0x96Du,
//                                 (v1 - 108),
//                                 (v1 - 100),
//                                 (v1 - 92),
//                                 (v1 - 20),
//                                 (v1 - 60),
//                                 (v1 - 44),
//                                 (v1 - 28),
//                                 (v1 - 84),
//                                 (v1 - 76),
//                                 (v1 - 68),
//                                 (v1 - 52),
//                                 v15,
//                                 -1,
//                                 v14,
//                                 -1,
//                                 "SUCS",
//                                 -1,
//                                 "SCRIPT",
//                                 -1);
                            Lua.lua_pushnumber(state, 1);
                            return 1;
                        }
// 
//                         v17 = v9;
//                         v18 = *(v3 + 108);
//                         *(v1 - 108) = v17;
//                         *(v1 - 104) = HIDWORD(v17);
//                         *(v1 - 100) = v18;
//                         LODWORD(v17) = *(v1 - 16);
//                         *(v1 - 92) = 0;
//                         *(v1 - 88) = 0;
//                         *(v1 - 96) = v18 >> 32;
//                         v17 = v17;
//                         *(v1 - 76) = v17;
//                         LODWORD(v17) = *(v1 - 24) + 100 * v7;
//                         *(v1 - 72) = HIDWORD(v17);
//                         v17 = v17;
//                         *(v1 - 68) = v17;
//                         LODWORD(v17) = *v3;
//                         *(v1 - 64) = HIDWORD(v17);
//                         v19 = (*(v17 + 64))(v3);
//                         *(v1 - 28) = v19;
//                         *(v1 - 24) = v19 >> 32;
//                         v20 = StructPlayer::GetAccountID(v3);
//                         *(v1 - 20) = v20;
//                         *(v1 - 84) = *(v3 + 4200);
//                         *(v1 - 80) = *(v3 + 4204);
//                         LODWORD(v20) = *v3;
//                         *(v1 - 16) = HIDWORD(v20);
//                         v21 = (*(v20 + 60))(v3);
//                         v22 = StructPlayer::GetAccountName(v3);
//                         LOG::Log11N4S(
//                             0x96Du,
//                             (v1 - 20),
//                             (v1 - 28),
//                             (v1 - 68),
//                             (v1 - 76),
//                             (v1 - 60),
//                             (v1 - 44),
//                             (v1 - 84),
//                             (v1 - 92),
//                             (v1 - 100),
//                             (v1 - 108),
//                             (v1 - 52),
//                             v22,
//                             -1,
//                             v21,
//                             -1,
//                             "FAIL",
//                             -1,
//                             "SCRIPT",
//                             -1);
                    }
                }
                Lua.lua_pushnumber(state, 0);
                return 1;
            }
            Lua.lua_pushnumber(state, 0.0);
            return 1;
        }


        public static int SCRIPT_InsertItem(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            double res = 0.0;
            int top = Lua.lua_gettop(state);

            int nCode;
            int nFlag;
            int nLevel;
            int nEnhance;
            int nCount;

            if (top >= 2)
            {
                nEnhance = -1;
                nLevel = -1;
                nFlag = -1;
                nCode = (int)Lua.lua_tonumber(state, 1);
                nCount = (int)Lua.lua_tonumber(state, 2);
                if (top >= 3 )
                    nEnhance = (int)Lua.lua_tonumber(state, 3);
                if (top >= 4 )
                    nLevel = (int)Lua.lua_tonumber(state, 4);
                if (top >= 5 )
                    nFlag = (int)Lua.lua_tonumber(state, 5);

                if (player != null
                  && nCount >= 1
                  && nLevel >= -1
                  && nEnhance >= -1)
                {
                    Item item = Item.AllocItem(0,nCode,nCount,ItemInstance.GenerateCode.ByScript,nLevel,-1,nEnhance,nFlag,0,0,0,0,-1,0,0,0,0);
                    Item pushedItem = player.PushItem(item, item.m_Instance.nCount, false);
                    ServerLog.Log((ushort)0x961,player.GetAccountID(),player.GetSID(),item.m_Instance.nLevel + 100 * item.m_Instance.nEnhance,
                        item.m_Instance.Code,item.m_Instance.nCount,(long)player.mv.x,(long)player.mv.y,0,player.m_nGold,0,0,
                        player.GetAccountName(),player.GetName(),"","SCRIPT");

                    if (pushedItem.m_hHandle != item.m_hHandle)
                        Item.PendFreeItem(item);
                    res = (double)pushedItem.m_hHandle;
                    if (res < 0 )
                        res += 4294967296.0;
                }
            }
            Lua.lua_pushnumber(state, res);
            return 1;

        }


        public static int SCRIPT_AddMonster(IntPtr state)
        {
            int x;
            int y;
            uint mob_id;
            int count;
            int i;
            string script = "";

            Player player = Instance.m_obj as Player;

            
            if (Lua.lua_gettop(state) >= 3 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0 && Lua.lua_isnumber(state, 3) != 0)
            {
                x = (int)Lua.lua_tonumber(state, 1);
                y = (int)Lua.lua_tonumber(state, 2);
                mob_id = (uint)Lua.lua_tonumber(state, 3);
                count = 1;

                if (Lua.lua_gettop(state) > 3 && Lua.lua_isnumber(state, 4) != 0 )
                    count = (int)Lua.lua_tonumber(state, 4);
                if (Lua.lua_gettop(state) > 4 && Lua.lua_isnumber(state, 5) == 0)
                    script = Lua.lua_tostring(state, 5);

                for (i = 0; i < count; ++i)
                {
                    Monster mob = Monster.AllocMonster(mob_id);
                    mob.strOnDeathScript = script;

                    if (mob == null)
                        break;

                    mob.m_nGenerateCode = 2;
                    mob.SetCurrentXY(x,y);
                    if (player != null)
                        mob.m_layer = player.m_layer;

                    RLock rl = RappelzServer.Instance._LockObjectWithVisibleRange(mob);
                    AutoLock al = new AutoLock(rl.handle);
                    GameContent.AddMonsterToWorld(mob);
//                    AutoLockDestroy((v1 - 68));
                }
                return 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddMonster() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_SpawnFieldProp(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            int top = Lua.lua_gettop(state);
            
            if (Lua.lua_gettop(state) >= 13 
                && Lua.lua_isnumber(state, 1) != 0 
                && Lua.lua_isnumber(state, 2) != 0
                && Lua.lua_isnumber(state, 3) != 0
                && Lua.lua_isnumber(state, 4) != 0
                && Lua.lua_isnumber(state, 5) != 0
                && Lua.lua_isnumber(state, 6) != 0
                && Lua.lua_isnumber(state, 7) != 0
                && Lua.lua_isnumber(state, 8) != 0
                && Lua.lua_isnumber(state, 9) != 0
                && Lua.lua_isnumber(state, 10) != 0
                && Lua.lua_isnumber(state, 11) != 0
                && Lua.lua_isnumber(state, 12) != 0 
                && Lua.lua_isnumber(state, 13) != 0)
            {
                GameContent.FieldPropRespawnInfo sr = new GameContent.FieldPropRespawnInfo();
                sr.nPropId = (int)Lua.lua_tonumber(state, 1);
                sr.x = (float)Lua.lua_tonumber(state, 2);
                sr.y = (float)Lua.lua_tonumber(state, 3);
                sr.fZOffset = (float)Lua.lua_tonumber(state, 4);
                sr.fRotateX = (float)Lua.lua_tonumber(state, 5);
                sr.fRotateY = (float)Lua.lua_tonumber(state, 6);
                sr.fRotateZ = (float)Lua.lua_tonumber(state, 7);
                sr.fScaleX = (float)Lua.lua_tonumber(state, 8);
                sr.fScaleY = (float)Lua.lua_tonumber(state, 9);
                sr.fScaleZ = (float)Lua.lua_tonumber(state, 10);
                sr.layer = (byte)Lua.lua_tonumber(state, 11);

                sr.bOnce = ((int)Lua.lua_tonumber(state, 13) != 0);

                //FieldPropManager.Instance.RegisterFieldProp(sr);

                int lifetime = (int)Lua.lua_tonumber(state, 12) * 100;
                FieldPropManager.Instance.SpawnFieldPropFromScript(sr, lifetime);

                return 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_SpawnFieldProp() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_AddHotspotSquare(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            int top = Lua.lua_gettop(state);
            
            if (Lua.lua_gettop(state) >= 7 
                && Lua.lua_isnumber(state, 1) != 0 
                && Lua.lua_isnumber(state, 2) != 0
                && Lua.lua_isnumber(state, 3) != 0
                && Lua.lua_isnumber(state, 4) != 0
                && Lua.lua_isnumber(state, 5) != 0
                && Lua.lua_isnumber(state, 6) != 0)
            {
                GameContent.HotSpot hs = new GameContent.HotSpot();
                hs.nQuestId = (int)Lua.lua_tonumber(state, 1);
                hs.x = (float)Lua.lua_tonumber(state, 2);
                hs.y = (float)Lua.lua_tonumber(state, 3);
                hs.sx = (float)Lua.lua_tonumber(state, 4);
                hs.sy = (float)Lua.lua_tonumber(state, 5);
                hs.regenTime = (uint)Lua.lua_tonumber(state, 6) * 100;
                hs.szEnterScript = Lua.lua_tostring(state,7);
                hs.bIsSquare = true;
                if(top >= 8)
                    hs.szExitScript = Lua.lua_tostring(state,8);
                if (top >= 9)
                    hs.nNeededStateId = (int)Lua.lua_tonumber(state, 9);

                player.AddHotspot(hs);

                return 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddHotspotSquare() : invalid argument");
            }
            return 1;
        }


        public static int SCRIPT_AddHotspot(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            int top = Lua.lua_gettop(state);
            
            if (Lua.lua_gettop(state) >= 6 
                && Lua.lua_isnumber(state, 1) != 0 
                && Lua.lua_isnumber(state, 2) != 0
                && Lua.lua_isnumber(state, 3) != 0
                && Lua.lua_isnumber(state, 4) != 0
                && Lua.lua_isnumber(state, 5) != 0)
            {
                GameContent.HotSpot hs = new GameContent.HotSpot();
                hs.nQuestId = (int)Lua.lua_tonumber(state, 1);
                hs.x = (float)Lua.lua_tonumber(state, 2);
                hs.y = (float)Lua.lua_tonumber(state, 3);
                hs.sx = (float)Lua.lua_tonumber(state, 4);
                hs.regenTime = (uint)Lua.lua_tonumber(state, 5);
                hs.szEnterScript = Lua.lua_tostring(state,6);
                hs.bIsSquare = false;
                if(top >= 7)
                    hs.szExitScript = Lua.lua_tostring(state,7);
                if (top >= 8)
                    hs.nNeededStateId = (int)Lua.lua_tonumber(state, 8);

                player.AddHotspot(hs);

                return 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_AddHotspotSquare() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_RemoveAllHotspots(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            int top = Lua.lua_gettop(state);

            if (Lua.lua_gettop(state) >= 1
                && Lua.lua_isnumber(state, 1) != 0)
            {
                int quest_id = (int)Lua.lua_tonumber(state, 1);
                player.RemoveHotspots(quest_id);

                return 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_RemoveAllHotspots() : invalid argument");
            }
            return 1;
        }


        public static int SCRIPT_ShowSoulStoneCraftWindow(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                Messages.SendShowSoulStoneCraftWindow(player);
                Lua.lua_pushnumber(state, 1.0);
                return 1;
            }
            return 0;
        }


        public static int SCRIPT_ShowSoulStoneRepairWindow(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (player != null)
            {
                Messages.SendShowSoulStoneRepairWindow(player);
                Lua.lua_pushnumber(state, 1.0);
                return 1;
            }
            return 0;
        }

        public static int SCRIPT_ShowQuestDialog(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            int top = Lua.lua_gettop(state);
            
            if (Lua.lua_gettop(state) >= 1 
                && Lua.lua_isnumber(state, 1) != 0)
            {
                int code = (int)Lua.lua_tonumber(state, 1);
                player.SetLastContact("npc", 0);
                Messages.SendQuestInformation(player, code, 0);
                player.ShowDialog();
                return 0;
            }
            else
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_ShowQuestDialog() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_ShowCreateGuild(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if(player != null)
                Messages.SendShowCreateGuild(player);
            return 0;
        }

//             m_instance.RegisterFunction(new Lua.LuaFunction(), "check_valid_guild_name");
//             m_instance.RegisterFunction(new Lua.LuaFunction(), "create_guild");
        public static int SCRIPT_CheckValidGuildName(IntPtr state)
        {
            if (Lua.lua_gettop(state) < 1 || Lua.lua_isstring(state, 1) == 0)
            {
                Lua.lua_pushnumber(state, 4.0);
                Error("SCRIPT_CheckValidGuildName() : invalid argument");
                return 1;
            }
            string name = Lua.lua_tostring(state,1);
            double res = 0.0;

            if (String.IsNullOrEmpty(name))
            {
                res = 2.0;
            }
            else if (GuildManager.Instance.IsExistGuild(name))
            {
                res = 3.0;
            }
            else if (!GameRule.IsValidName(name, name.Length, 1, 16) || GameContent.IsBannedWord(name))
            {
                res = 2.0;
            }

            Lua.lua_pushnumber(state, res);
            return 1;
        }

        public static int SCRIPT_CreateGuild(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            string strMsg;
            string szGuildName;

            if (Lua.lua_gettop(state) < 1 || Lua.lua_isstring(state, 1) == 0)
            {
                Lua.lua_pushnumber(state, 4.0);
                Error("SCRIPT_CreateGuild() : invalid argument");
                return 1;
            }
            
            double res = 0.0;
            szGuildName = Lua.lua_tostring(state, 1);
            if (String.IsNullOrEmpty(szGuildName) 
                || szGuildName.Length > 16
                || !GameRule.IsValidName(szGuildName,szGuildName.Length, 1, 16)
                || GameContent.IsBannedWord(szGuildName))
            {
                Lua.lua_pushnumber(state, 2.0);
                return 1;
            }

            if (player.m_nGuildId <= 0 )
            {
                if (player.GetPrevGuildID() != 0)
                {
                    res = 5.0;
                }
                else
                {
                    if (GuildManager.Instance.MakeGuild(szGuildName, player.m_nUID))
                    {
                        GuildManager.Instance.JoinGuild(szGuildName, player);
                        player.Save(true);
                        Lua.lua_pushnumber(state, 0.0);
                        strMsg = String.Format("@601\v#@guild_name@#\v{0}\v#@user_name@#\v{1}", szGuildName,player.GetName());
                        Messages.SendGlobalChatMessage(4, "@GUILD", strMsg, 0);
                        Messages.SendGuildNotify(player);
                        Messages.SendGuildInfo(player);
                        ServerLog.Log((ushort)0xB55,player.GetAccountID(),player.GetSID(),0,player.m_nGuildId,0,0,0,0,0,0,0,
                            player.GetAccountName(),player.GetName(),szGuildName,"");
                        return 1;
                    }
                    res = 3.0;
                }
            }
            else
            {
                res = 1.0;
            }
            Lua.lua_pushnumber(state, res);

            return 1;
        }

        public static int SCRIPT_SpawnedCount(IntPtr state)
        {
            Player player = Instance.m_obj as Player;
            double res = 0.0;

            if (Lua.lua_gettop(state) == 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                res = (double)MemoryPool.GetMonsterCount((int)Lua.lua_tonumber(state, 1));
                Lua.lua_pushnumber(state, res);

            }
            else if (Lua.lua_gettop(state) == 2 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0)
            {
                res = (double)MemoryPool.GetMonsterCountFromParent((int)Lua.lua_tonumber(state, 1), (uint)Lua.lua_tonumber(state, 2));
                Lua.lua_pushnumber(state, res);

            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_SpawnedCount() : invalid argument");
            }

            return 1;
        }

        public static int SCRIPT_UpdateQuest(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 3 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0 && Lua.lua_isnumber(state, 3) != 0)
            {
                if (player == null)
                {
                    return 0;
                }
                int id = (int)Lua.lua_tonumber(state, 1);
                int idx = (int)Lua.lua_tonumber(state, 2);
                int value = (int)Lua.lua_tonumber(state, 3);
                player.UpdateQuestStatusByScript(id, idx, value);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_UpdateQuest() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_StartQuestTimer(IntPtr state)
        {
            Player player = Instance.m_obj as Player;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                if (player == null)
                {
                    return 0;
                }
                int id = (int)Lua.lua_tonumber(state, 1);
//                player.UpdateQuestStatusByScript(id, idx, value);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_StartQuestTimer() : invalid argument");
            }
            return 1;
        }


        public static int SCRIPT_GetMonsterID(IntPtr state)
        {
            double res = 0.0;
            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0)
            {
                Monster mob = Monster.get((uint)Lua.lua_tonumber(state, 1)) as Monster;
                if (mob != null)
                {
                    res = (double) mob.GetMonsterId();
                }
                Lua.lua_pushnumber(state, res);
            }
            else
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_GetMonsterID() : invalid argument");
            }
            return 1;
        }

        public static int SCRIPT_RespawnNearMonster(IntPtr state)
        {
            ArPosition targetPos;
            ArPosition pos;
            int monster_id;
            int dungeon_id;
            float x;
            float y;
            bool bValidPos;

            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0 && Lua.lua_isnumber(state, 3) != 0)
            {
                uint mob_handle = (uint)Lua.lua_tonumber(state, 1);
                monster_id = (int)Lua.lua_tonumber(state, 2);
                int mob_cnt = (int)Lua.lua_tonumber(state, 3);
                Monster mob = Monster.get(mob_handle) as Monster;
                if (mob != null && mob.m_nHP != 0)
                {
                    uint ct = Globals.GetArTime();
                    pos = mob.GetCurrentPosition(ct);
                    for(int i = 0; i < mob_cnt; ++i)
                    {
                        bValidPos = false;
                        x = Globals.GetRandomInt32((int)(pos.x-60),(int)(pos.x+60));
                        y = Globals.GetRandomInt32((int)(pos.y-60),(int)(pos.y+60));
                        for(int z = 0; z < 300;++z)
                        {
                            if (!GameContent.IsBlocked(x,y))
                            {
                                bValidPos = true;
                                break;
                            };
                        }
                        if (bValidPos)
                        {
                            Monster nm = GameContent.respawnMonster((uint)x,(uint)y, mob.m_layer, (uint)monster_id, true, 0, null, false);
                            if (nm != null)
                            {
                                targetPos = new ArPosition(x,y,0);
                                nm.SetMove(targetPos,(byte)(3*nm.GetMoveSpeed() / 7),0);
                                nm.m_bRespawnByScript = true;
                                RappelzServer.Instance.SetObjectPriority(nm, SchedulerObject.Priority.Highest);
                                nm.m_hParent = mob.m_hHandle;
                                if (mob.m_bIsDungeonRaidMonster)
                                {
                                    dungeon_id = ChannelManager.GetChannelId(x,y);
                                    if (dungeon_id != 0)
                                    {
                                        if (ChannelManager.GetChannelType(dungeon_id) == 2)
                                        {
                                            nm.m_bIsDungeonRaidMonster = true;
                                            nm.CalculateStat();
//                                                             *(v1 - 60) = v5->baseclass_0.baseclass_0.baseclass_0.layer;
//                                                             v25 = *(v1 - 60);
//                                                             v26 = *(v1 - 28);
//                                                             DungeonManager.Instance.AddToDungeonRaidMonster(v27, v20, v26, v25);
                                        }
                                    }
                                }
                            if (mob.m_hEnemy != 0)
                                nm.AddHate(mob.m_hEnemy, 1, true, true);
                            }
                        }
                    }
                }
            }
            else
            {
                Error("SCRIPT_RespawnNearMonster() : invalid argument");
            }
            return 0;

        }

        public static int SCRIPT_MonsterSkillCast(IntPtr state)
        {
            if (Lua.lua_gettop(state) >= 1 && Lua.lua_isnumber(state, 1) != 0 && Lua.lua_isnumber(state, 2) != 0 && Lua.lua_isnumber(state, 3) != 0)
            {
                int skill_idx = (int)Lua.lua_tonumber(state, 1);
                uint hCaster = (uint)Lua.lua_tonumber(state, 2);
                uint hTarget = (uint)Lua.lua_tonumber(state, 3);
                Monster caster = Monster.get(hCaster) as Monster;

                if (caster != null && caster.m_nHP != 0)
                {
                    Creature target = Creature.get(hTarget) as Creature;
                    if (target != null && target.m_nHP != 0)
                    {
                        MonsterBase.MonsterSkillInfo msi = caster.m_pContentInfo.skill_info[skill_idx];
                        if (caster.CastSkill(msi.skill_id,msi.skill_lvl,hTarget,caster.GetCurrentPosition(Globals.GetArTime()),caster.m_layer,false) != 0)
                            caster.m_bContinueAttack = true;
                    }
                }
            }
            else
            {
                Error("SCRIPT_MonsterSkillCast() : invalid argument");
            }
            return 0;

        }

        public static int SCRIPT_GetDungeonRelation(IntPtr state)
        {
            int raid_guild_id;
            int alliance_id;
            double res = 0.0;

            if (Lua.lua_gettop(state) < 1 || Lua.lua_isnumber(state, 1) == 0)
            {
                Lua.lua_pushstring(state, "invalid argument");
                Error("SCRIPT_GetDungeonRelation() : invalid argument");
                return 1;
            }

            Player player = Instance.m_obj as Player;

            raid_guild_id = (int)Lua.lua_tonumber(state, 1);

            if (player == null)
            {
                Lua.lua_pushnumber(state, 0.0);
                Error("SCRIPT_GetDungeonRelation() : invalid name");
                return 1;
            }

            alliance_id = GuildManager.Instance.GetAllianceID(player.m_nGuildId);
            if (player.m_nGuildId != 0)
            {
                int nDungeonGuildId = DungeonManager.Instance.GetOwnGuildID(raid_guild_id);
                raid_guild_id = DungeonManager.Instance.GetRaidGuildID(raid_guild_id);
                if (nDungeonGuildId != 0 && player.m_nGuildId == nDungeonGuildId)
                {
                    if (GuildManager.Instance.IsLeader(player.m_nGuildId,player.GetName()) )
                        res = 1.0;
                    else
                        res = 2.0;
                }
                else if (alliance_id != 0 && GuildManager.Instance.GetAllianceLeaderGuildID(alliance_id) == nDungeonGuildId)
                {
                    if (GuildManager.Instance.IsLeader(player.m_nGuildId,player.GetName()))
                        res = 3.0;
                    else
                        res = 4.0;
                }
                else if (raid_guild_id != 0 && player.m_nGuildId == raid_guild_id)
                {
                    if (GuildManager.Instance.IsLeader(player.m_nGuildId,player.GetName()))
                        res = 5.0;
                    else
                        res = 6.0;
                }
                else if (alliance_id != 0 && GuildManager.Instance.GetAllianceLeaderGuildID(alliance_id) == raid_guild_id)
                {
                    if (GuildManager.Instance.IsLeader(player.m_nGuildId,player.GetName()))
                        res = 7.0;
                    else
                        res = 8.0;
                }
            }

            Lua.lua_pushnumber(state, res);
            return 1;
        }



    }
    
}
